diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index 85896cf8e7ee7d2ce6562130dd412c79aed31a5d..824fccceb22f316d74901658c171f3400261fcab 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -111,7 +111,9 @@ public: /// previously marked as declaretarget. /// /// \param D the declaration marked OpenMP declaretarget. - virtual void DeclarationMarkedOpenMPDeclareTarget(const Decl *D) {} + /// \param Attr the added attribute. + virtual void DeclarationMarkedOpenMPDeclareTarget(const Decl *D, + const Attr *Attr) {} /// \brief A definition has been made visible by being redefined locally. /// diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index df41aebf457b90932c000764515fafd4274c64f1..e3c5e442651546ec5132bbcb2e5e717f5fd1da19 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -2345,8 +2345,17 @@ def OMPDeclareTargetDecl : Attr { let Spellings = [Pragma<"omp", "declare target">]; let SemaHandler = 0; let Documentation = [OMPDeclareTargetDocs]; + let Args = [ + EnumArgument<"MapType", "MapTypeTy", + [ "to", "link" ], + [ "MT_To", "MT_Link" ]> + ]; let AdditionalMembers = [{ - void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {} + void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const { + // Use fake syntax because it is for testing and debugging purpose only. + if (getMapType() != MT_To) + OS << ConvertMapTypeTyToStr(getMapType()) << " "; + } }]; } diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 04e7984734e5b1310edb3c90bb529d4eba5245e2..c3eea00e1be4125c8a005c61d92e81e55a9783f6 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -967,6 +967,8 @@ def err_omp_declare_simd_inbranch_notinbranch : Error< "unexpected '%0' clause, '%1' is specified already">; def err_expected_end_declare_target : Error< "expected '#pragma omp end declare target'">; +def err_omp_declare_target_unexpected_clause: Error< + "unexpected '%0' clause, only 'to' or 'link' clauses expected">; // Pragma loop support. def err_pragma_loop_missing_argument : Error< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a6cdfa20ce99f66b5ccdbbcd1b873ef763bf2a03..ea0d52a05fdd0f5d8201780c6e46df975581d97e 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -7984,6 +7984,12 @@ def warn_omp_alignment_not_power_of_two : Warning< InGroup<OpenMPClauses>; def err_omp_enclosed_declare_target : Error< "declare target region may not be enclosed within another declare target region">; +def err_omp_invalid_target_decl : Error< + "%0 used in declare target directive is not a variable or a function name">; +def err_omp_declare_target_multiple : Error< + "%0 appears multiple times in clauses on the same declare target directive">; +def err_omp_declare_target_to_and_link : Error< + "%0 must not appear in both clauses 'to' and 'link'">; def warn_omp_not_in_target_context : Warning< "declaration is not declared in any declare target region">, InGroup<OpenMPTarget>; diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 6b586ddbbc4eff0953290cad06c24d3f703a5063..f4688798055703f3c9b1df97dd12b197dff9df25 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -2466,16 +2466,19 @@ private: Decl *TagDecl = nullptr); /// \brief Parse 'omp declare reduction' construct. DeclGroupPtrTy ParseOpenMPDeclareReductionDirective(AccessSpecifier AS); + /// \brief Parses simple list of variables. /// /// \param Kind Kind of the directive. - /// \param [out] VarList List of referenced variables. + /// \param Callback Callback function to be called for the list elements. /// \param AllowScopeSpecifier true, if the variables can have fully /// qualified names. /// - bool ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, - SmallVectorImpl<Expr *> &VarList, - bool AllowScopeSpecifier); + bool ParseOpenMPSimpleVarList( + OpenMPDirectiveKind Kind, + const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> & + Callback, + bool AllowScopeSpecifier); /// \brief Parses declarative or executable directive. /// /// \param Allowed ACK_Any, if any directives are allowed, diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index c263fd50f332719436e4e85b4033e940bcb573a6..d7e56f78f7f26e8613930350465d4f2e18e76fbc 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -7977,6 +7977,11 @@ public: bool ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc); /// Called at the end of target region i.e. '#pragme omp end declare target'. void ActOnFinishOpenMPDeclareTargetDirective(); + /// Called on correct id-expression from the '#pragma omp declare target'. + void ActOnOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, + const DeclarationNameInfo &Id, + OMPDeclareTargetDeclAttr::MapTypeTy MT, + NamedDeclSetType &SameDirectiveDecls); /// Check declaration inside target region. void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D); /// Return true inside OpenMP target region. diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index bf53cf09bef0691abd52e9b57d2caab8e08a1d0e..bfdb9f2262b50fa8986cb8b7ad4d817b44f05130 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -682,7 +682,8 @@ private: const ObjCInterfaceDecl *IFD) override; void DeclarationMarkedUsed(const Decl *D) override; void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override; - void DeclarationMarkedOpenMPDeclareTarget(const Decl *D) override; + void DeclarationMarkedOpenMPDeclareTarget(const Decl *D, + const Attr *Attr) override; void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override; void AddedAttributeToRecord(const Attr *Attr, const RecordDecl *Record) override; diff --git a/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp index 581ed13ce09cbee14e3b5a1c473a0bd85e2835a1..17cdaee4be05cc79034cac24e7283a0117a950dd 100644 --- a/lib/Frontend/MultiplexConsumer.cpp +++ b/lib/Frontend/MultiplexConsumer.cpp @@ -125,7 +125,8 @@ public: void FunctionDefinitionInstantiated(const FunctionDecl *D) override; void DeclarationMarkedUsed(const Decl *D) override; void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override; - void DeclarationMarkedOpenMPDeclareTarget(const Decl *D) override; + void DeclarationMarkedOpenMPDeclareTarget(const Decl *D, + const Attr *Attr) override; void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override; void AddedAttributeToRecord(const Attr *Attr, const RecordDecl *Record) override; @@ -221,9 +222,9 @@ void MultiplexASTMutationListener::DeclarationMarkedOpenMPThreadPrivate( Listeners[i]->DeclarationMarkedOpenMPThreadPrivate(D); } void MultiplexASTMutationListener::DeclarationMarkedOpenMPDeclareTarget( - const Decl *D) { + const Decl *D, const Attr *Attr) { for (auto *L : Listeners) - L->DeclarationMarkedOpenMPDeclareTarget(D); + L->DeclarationMarkedOpenMPDeclareTarget(D, Attr); } void MultiplexASTMutationListener::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) { diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index b1538fde257cc59a8c76c35e5370518f0afbc552..5a3b4ac825c1778ea8c259f53b1e43f1f64ddb93 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -40,6 +40,21 @@ enum OpenMPDirectiveKindEx { OMPD_target_enter, OMPD_target_exit }; + +class ThreadprivateListParserHelper final { + SmallVector<Expr *, 4> Identifiers; + Parser *P; + +public: + ThreadprivateListParserHelper(Parser *P) : P(P) {} + void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { + ExprResult Res = + P->getActions().ActOnOpenMPIdExpression(P->getCurScope(), SS, NameInfo); + if (Res.isUsable()) + Identifiers.push_back(Res.get()); + } + llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; } +}; } // namespace // Map token string to extended OMP token kind that are @@ -525,13 +540,13 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( ParenBraceBracketBalancer BalancerRAIIObj(*this); SourceLocation Loc = ConsumeToken(); - SmallVector<Expr *, 4> Identifiers; auto DKind = ParseOpenMPDirectiveKind(*this); switch (DKind) { - case OMPD_threadprivate: + case OMPD_threadprivate: { ConsumeToken(); - if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) { + ThreadprivateListParserHelper Helper(this); + if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) { // The last seen token is annot_pragma_openmp_end - need to check for // extra tokens. if (Tok.isNot(tok::annot_pragma_openmp_end)) { @@ -541,9 +556,11 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( } // Skip the last annot_pragma_openmp_end. ConsumeToken(); - return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers); + return Actions.ActOnOpenMPThreadprivateDirective(Loc, + Helper.getIdentifiers()); } break; + } case OMPD_declare_reduction: ConsumeToken(); if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) { @@ -599,10 +616,40 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_declare_target: { SourceLocation DTLoc = ConsumeAnyToken(); if (Tok.isNot(tok::annot_pragma_openmp_end)) { - Diag(Tok, diag::warn_omp_extra_tokens_at_eol) - << getOpenMPDirectiveName(OMPD_declare_target); + // OpenMP 4.5 syntax with list of entities. + llvm::SmallSetVector<const NamedDecl*, 16> SameDirectiveDecls; + while (Tok.isNot(tok::annot_pragma_openmp_end)) { + OMPDeclareTargetDeclAttr::MapTypeTy MT = + OMPDeclareTargetDeclAttr::MT_To; + if (Tok.is(tok::identifier)) { + IdentifierInfo *II = Tok.getIdentifierInfo(); + StringRef ClauseName = II->getName(); + // Parse 'to|link' clauses. + if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, + MT)) { + Diag(Tok, diag::err_omp_declare_target_unexpected_clause) + << ClauseName; + break; + } + ConsumeToken(); + } + auto Callback = [this, MT, &SameDirectiveDecls]( + CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { + Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT, + SameDirectiveDecls); + }; + if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, true)) + break; + + // Consume optional ','. + if (Tok.is(tok::comma)) + ConsumeToken(); + } SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); + ConsumeAnyToken(); + return DeclGroupPtrTy(); } + // Skip the last annot_pragma_openmp_end. ConsumeAnyToken(); @@ -716,7 +763,6 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( AllowedContsructsKind Allowed) { assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); ParenBraceBracketBalancer BalancerRAIIObj(*this); - SmallVector<Expr *, 5> Identifiers; SmallVector<OMPClause *, 5> Clauses; SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> FirstClauses(OMPC_unknown + 1); @@ -732,13 +778,14 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( bool FlushHasClause = false; switch (DKind) { - case OMPD_threadprivate: + case OMPD_threadprivate: { if (Allowed != ACK_Any) { Diag(Tok, diag::err_omp_immediate_directive) << getOpenMPDirectiveName(DKind) << 0; } ConsumeToken(); - if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) { + ThreadprivateListParserHelper Helper(this); + if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) { // The last seen token is annot_pragma_openmp_end - need to check for // extra tokens. if (Tok.isNot(tok::annot_pragma_openmp_end)) { @@ -746,12 +793,13 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( << getOpenMPDirectiveName(OMPD_threadprivate); SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); } - DeclGroupPtrTy Res = - Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers); + DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective( + Loc, Helper.getIdentifiers()); Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); } SkipUntil(tok::annot_pragma_openmp_end); break; + } case OMPD_declare_reduction: ConsumeToken(); if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { @@ -913,16 +961,15 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( return Directive; } -/// \brief Parses list of simple variables for '#pragma omp threadprivate' -/// directive. -/// -/// simple-variable-list: -/// '(' id-expression {, id-expression} ')' -/// -bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, - SmallVectorImpl<Expr *> &VarList, - bool AllowScopeSpecifier) { - VarList.clear(); +// Parses simple list: +// simple-variable-list: +// '(' id-expression {, id-expression} ')' +// +bool Parser::ParseOpenMPSimpleVarList( + OpenMPDirectiveKind Kind, + const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> & + Callback, + bool AllowScopeSpecifier) { // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, @@ -959,11 +1006,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, << tok::identifier << SourceRange(PrevTok.getLocation(), PrevTokLocation); } else { - DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name); - ExprResult Res = - Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo); - if (Res.isUsable()) - VarList.push_back(Res.get()); + Callback(SS, Actions.GetNameFromUnqualifiedId(Name)); } // Consume ','. if (Tok.is(tok::comma)) { @@ -979,7 +1022,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, // Parse ')'. IsCorrect = !T.consumeClose() && IsCorrect; - return !IsCorrect && VarList.empty(); + return !IsCorrect; } /// \brief Parsing of OpenMP clauses. diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index cbcf70b41fc02a8820ce2bd173069584851ebc71..ea26f6a4f16dc0b46820c6705e798eb20a3acf56 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -1101,6 +1101,23 @@ public: return false; } }; + +class VarOrFuncDeclFilterCCC : public CorrectionCandidateCallback { +private: + Sema &SemaRef; + +public: + explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {} + bool ValidateCandidate(const TypoCorrection &Candidate) override { + NamedDecl *ND = Candidate.getCorrectionDecl(); + if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) { + return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), + SemaRef.getCurScope()); + } + return false; + } +}; + } // namespace ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope, @@ -10752,6 +10769,52 @@ void Sema::ActOnFinishOpenMPDeclareTargetDirective() { IsInOpenMPDeclareTargetContext = false; } +void +Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, + const DeclarationNameInfo &Id, + OMPDeclareTargetDeclAttr::MapTypeTy MT, + NamedDeclSetType &SameDirectiveDecls) { + LookupResult Lookup(*this, Id, LookupOrdinaryName); + LookupParsedName(Lookup, CurScope, &ScopeSpec, true); + + if (Lookup.isAmbiguous()) + return; + Lookup.suppressDiagnostics(); + + if (!Lookup.isSingleResult()) { + if (TypoCorrection Corrected = + CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, + llvm::make_unique<VarOrFuncDeclFilterCCC>(*this), + CTK_ErrorRecovery)) { + diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest) + << Id.getName()); + checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl()); + return; + } + + Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName(); + return; + } + + NamedDecl *ND = Lookup.getAsSingle<NamedDecl>(); + if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) { + if (!SameDirectiveDecls.insert(cast<NamedDecl>(ND->getCanonicalDecl()))) + Diag(Id.getLoc(), diag::err_omp_declare_target_multiple) << Id.getName(); + + if (!ND->hasAttr<OMPDeclareTargetDeclAttr>()) { + Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT); + ND->addAttr(A); + if (ASTMutationListener *ML = Context.getASTMutationListener()) + ML->DeclarationMarkedOpenMPDeclareTarget(ND, A); + checkDeclIsAllowedInOpenMPTarget(nullptr, ND); + } else if (ND->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() != MT) { + Diag(Id.getLoc(), diag::err_omp_declare_target_to_and_link) + << Id.getName(); + } + } else + Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName(); +} + static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, Sema &SemaRef, Decl *D) { if (!D) @@ -10765,9 +10828,11 @@ static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, // If this is an implicit variable that is legal and we do not need to do // anything. if (cast<VarDecl>(D)->isImplicit()) { - D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(SemaRef.Context)); + Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit( + SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To); + D->addAttr(A); if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(D); + ML->DeclarationMarkedOpenMPDeclareTarget(D, A); return; } @@ -10780,9 +10845,11 @@ static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, // target region (it can be e.g. a lambda) that is legal and we do not need // to do anything else. if (LD == D) { - D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(SemaRef.Context)); + Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit( + SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To); + D->addAttr(A); if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(D); + ML->DeclarationMarkedOpenMPDeclareTarget(D, A); return; } } @@ -10810,9 +10877,11 @@ static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, SemaRef.Diag(SL, diag::note_used_here) << SR; } // Mark decl as declared target to prevent further diagnostic. - D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(SemaRef.Context)); + Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit( + SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To); + D->addAttr(A); if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(D); + ML->DeclarationMarkedOpenMPDeclareTarget(D, A); } } @@ -10846,9 +10915,11 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D) { !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD)) { // Mark decl as declared target to prevent further diagnostic. if (isa<VarDecl>(VD) || isa<FunctionDecl>(VD)) { - VD->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(Context)); + Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit( + Context, OMPDeclareTargetDeclAttr::MT_To); + VD->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(VD); + ML->DeclarationMarkedOpenMPDeclareTarget(VD, A); } return; } @@ -10857,9 +10928,11 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D) { // Checking declaration inside declare target region. if (!D->hasAttr<OMPDeclareTargetDeclAttr>() && (isa<VarDecl>(D) || isa<FunctionDecl>(D))) { - D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(Context)); + Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit( + Context, OMPDeclareTargetDeclAttr::MT_To); + D->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(D); + ML->DeclarationMarkedOpenMPDeclareTarget(D, A); } return; } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 1a013cee2198926991ab808b4266dc70fe4f1a43..6b933f2bba10bf7c57403023fd37cc6d98c8fdb9 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -3890,11 +3890,6 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, Reader.Context, ReadSourceRange(Record, Idx))); break; - case UPD_DECL_MARKED_OPENMP_DECLARETARGET: - D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit( - Reader.Context, ReadSourceRange(Record, Idx))); - break; - case UPD_DECL_EXPORTED: { unsigned SubmoduleID = readSubmoduleID(Record, Idx); auto *Exported = cast<NamedDecl>(D); @@ -3920,6 +3915,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, break; } + case UPD_DECL_MARKED_OPENMP_DECLARETARGET: case UPD_ADDED_ATTR_TO_RECORD: AttrVec Attrs; Reader.ReadAttributes(F, Attrs, Record, Idx); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 606228af75369c4cef3bca10ddf76c5063292b21..29a20b2e45e1f7dea5649746755188e2d55063d9 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -5816,12 +5816,14 @@ void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) { DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_THREADPRIVATE)); } -void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D) { +void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D, + const Attr *Attr) { assert(!WritingAST && "Already writing the AST!"); if (!D->isFromASTFile()) return; - DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_DECLARETARGET)); + DeclUpdates[D].push_back( + DeclUpdate(UPD_DECL_MARKED_OPENMP_DECLARETARGET, Attr)); } void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) { diff --git a/test/OpenMP/declare_target_ast_print.cpp b/test/OpenMP/declare_target_ast_print.cpp index 53e0d764e8291b44acb5e0f6dd427e0e40c498f3..78a9cf634af89e9864287ff222a26759e3ef2991 100644 --- a/test/OpenMP/declare_target_ast_print.cpp +++ b/test/OpenMP/declare_target_ast_print.cpp @@ -79,6 +79,51 @@ int test1() { #pragma omp end declare target // CHECK: #pragma omp end declare target +int a1; +void f1() { +} +#pragma omp declare target (a1, f1) +// CHECK: #pragma omp declare target +// CHECK: int a1; +// CHECK: #pragma omp end declare target +// CHECK: #pragma omp declare target +// CHECK: void f1() +// CHECK: #pragma omp end declare target + +int b1, b2, b3; +void f2() { +} +#pragma omp declare target to(b1) to(b2), to(b3, f2) +// CHECK: #pragma omp declare target +// CHECK: int b1; +// CHECK: #pragma omp end declare target +// CHECK: #pragma omp declare target +// CHECK: int b2; +// CHECK: #pragma omp end declare target +// CHECK: #pragma omp declare target +// CHECK: int b3; +// CHECK: #pragma omp end declare target +// CHECK: #pragma omp declare target +// CHECK: void f2() +// CHECK: #pragma omp end declare target + +int c1, c2, c3; +void f3() { +} +#pragma omp declare target link(c1) link(c2), link(c3, f3) +// CHECK: #pragma omp declare target link +// CHECK: int c1; +// CHECK: #pragma omp end declare target +// CHECK: #pragma omp declare target link +// CHECK: int c2; +// CHECK: #pragma omp end declare target +// CHECK: #pragma omp declare target link +// CHECK: int c3; +// CHECK: #pragma omp end declare target +// CHECK: #pragma omp declare target link +// CHECK: void f3() +// CHECK: #pragma omp end declare target + int main (int argc, char **argv) { foo(); foo_c(); diff --git a/test/OpenMP/declare_target_messages.cpp b/test/OpenMP/declare_target_messages.cpp index 50f0ed98fcb4fbc2e30c5d7510c723d783e93ae8..b858d53c1ecf573402bceac1120c72b86e6a541d 100644 --- a/test/OpenMP/declare_target_messages.cpp +++ b/test/OpenMP/declare_target_messages.cpp @@ -4,9 +4,15 @@ int a, b; // expected-warning {{declaration is not declared in any declare target region}} __thread int t; // expected-note {{defined as threadprivate or thread local}} -#pragma omp declare target private(a) // expected-warning {{extra tokens at the end of '#pragma omp declare target' are ignored}} + +#pragma omp declare target . // expected-error {{expected '(' after 'declare target'}} + +#pragma omp declare target void f(); #pragma omp end declare target shared(a) // expected-warning {{extra tokens at the end of '#pragma omp end declare target' are ignored}} + +#pragma omp declare target map(a) // expected-error {{unexpected 'map' clause, only 'to' or 'link' clauses expected}} + void c(); // expected-warning {{declaration is not declared in any declare target region}} extern int b; @@ -86,4 +92,10 @@ namespace { } // expected-error {{expected '#pragma omp end declare target'}} #pragma omp end declare target // expected-error {{unexpected OpenMP directive '#pragma omp end declare target'}} +#pragma omp declare target link(S) // expected-error {{'S' used in declare target directive is not a variable or a function name}} + +#pragma omp declare target (x, x) // expected-error {{'x' appears multiple times in clauses on the same declare target directive}} +#pragma omp declare target to(x) to(x) // expected-error {{'x' appears multiple times in clauses on the same declare target directive}} +#pragma omp declare target link(x) // expected-error {{'x' must not appear in both clauses 'to' and 'link'}} + #pragma omp declare target // expected-error {{expected '#pragma omp end declare target'}} expected-note {{to match this '#pragma omp declare target'}}