diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -1767,7 +1767,8 @@ None, Target, CPUSpecific, - CPUDispatch + CPUDispatch, + OpenMPVariant, }; /// Represents a function declaration or definition. @@ -2375,6 +2376,10 @@ /// the target functionality. bool isTargetMultiVersion() const; + /// True if this function is a multiversioned function as a part of + /// the OpenMP begin/end declare variant functionality. + bool isOpenMPVariantMultiVersion() const; + /// \brief Get the associated-constraints of this function declaration. /// Currently, this will either be a vector of size 1 containing the /// trailing-requires-clause or an empty vector. diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -101,6 +101,10 @@ [{!S->isStatic() && !S->isConst()}], "non-static non-const member functions">; +def FunctionDefinition : SubsetSubjectisThisDeclarationADefinition()}], + "function definition">; + def ObjCInstanceMethod : SubsetSubjectisInstanceMethod()}], "Objective-C instance methods">; @@ -417,8 +421,11 @@ def SubRuleForCXXMethod : AttrSubjectMatcherSubRule<"is_member", [CXXMethod]> { let LangOpts = [CPlusPlus]; } +// function(is_definition) +def SubRuleForFunctionDefiniton + : AttrSubjectMatcherSubRule<"is_definition", [FunctionDefinition]> {} def SubjectMatcherForFunction : AttrSubjectMatcherRule<"function", [Function], [ - SubRuleForCXXMethod + SubRuleForCXXMethod, SubRuleForFunctionDefiniton ]>; // hasType is abstract, it should be used with one of the sub-rules. def SubjectMatcherForType : AttrSubjectMatcherRule<"hasType", [], [ @@ -3381,6 +3388,33 @@ }]; } +def OMPMultiVersionDeclareVariant : Attr { + let Spellings = [Pragma<"omp", "begin declare variant">]; + let Subjects = SubjectList<[FunctionDefinition]>; + let SemaHandler = 1; + let HasCustomParsing = 1; + let PragmaAttributeSupport = 1; + let Documentation = [OMPMultiVersionDeclareVariantDocs]; + let Args = [ + OMPTraitInfoArgument<"TraitInfos">, + ]; + let AdditionalMembers = [{ + OMPTraitInfo &getTraitInfo() { return traitInfos; } + void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy) + const { + OS << " match("; + traitInfos.print(OS, Policy); + OS << ")"; + } + }]; +} + +def OMPMultiVersionDeclareBase : InheritableAttr { + let Spellings = []; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; +} + def InternalLinkage : InheritableAttr { let Spellings = [Clang<"internal_linkage">]; let Subjects = SubjectList<[Var, Function, CXXRecord]>; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3396,6 +3396,32 @@ }]; } +def OMPMultiVersionDeclareVariantDocs : Documentation { + let Category = DocCatFunction; + let Heading = "#pragma omp begin declare variant"; + let Content = [{ +The `begin declare variant` and `end declare variant` directives declare +enclosed functions definitions to be specialized variants of their respective +base functions with the same name. The `begin declare variant` specifies the +context in which that specialized variant is used. The declare variant +directive is a declarative directive. The syntax of the `declare variant` +construct is as follows: + + .. code-block:: none + + #pragma omp begin declare variant clause new-line + [...] + #pragma omp end declare variant new-line + +where clause is one of the following: + + .. code-block:: none + + match(context-selector-specification) + + }]; +} + def NoStackProtectorDocs : Documentation { let Category = DocCatFunction; let Content = [{ diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1248,6 +1248,9 @@ "unexpected '%0' clause, '%1' is specified already">; def err_expected_end_declare_target_or_variant : Error< "expected '#pragma omp end declare %select{target|variant}0'">; +def err_expected_begin_declare_variant + : Error<"expected '#pragma omp begin declare variant' to match this stray " + "`#pragma omp end delcare variant`">; def err_omp_declare_target_unexpected_clause: Error< "unexpected '%0' clause, only %select{'to' or 'link'|'to', 'link' or 'device_type'}1 clauses expected">; def err_omp_expected_clause: Error< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10110,6 +10110,15 @@ "'flush' directive with memory order clause '%0' cannot have the list">; def note_omp_flush_order_clause_here : Note< "memory order clause '%0' is specified here">; + +def warn_nested_declare_variant + : Warning<"nesting `omp begin/end declare variant` is not supported yet; " + "nested context ignored">, + InGroup; +def err_implicit_declare_variant_base_selected + : Error<"implicitly declared base function for the specialized OpenMP " + "function %0 cannot be used but no specialization was applicable">; + } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { @@ -10506,9 +10515,10 @@ "multiversioned function redeclarations require identical target attributes">; def err_multiversion_noproto : Error< "multiversioned function must have a prototype">; -def err_multiversion_no_other_attrs : Error< - "attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioning cannot be combined" - " with other attributes">; +def err_multiversion_no_other_attrs + : Error< + "attribute '%select{none|target|cpu_specific|cpu_dispatch|OpenMP}0' " + "multiversioning cannot be combined with other attributes">; def err_multiversion_diff : Error< "multiversioned function declaration has a different %select{calling convention" "|return type|constexpr specification|inline specification|storage class|" diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3796,6 +3796,10 @@ SourceLocation Loc); NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, Scope *S); + FunctionDecl *CreateImplicitlyDefinedFunction(SourceLocation Loc, + SourceRange SR, + DeclaratorContext DC, + IdentifierInfo &II, Scope *S); void AddKnownFunctionAttributes(FunctionDecl *FD); // More parsing and symbol table subroutines. @@ -5094,7 +5098,8 @@ SourceLocation IdentLoc, IdentifierInfo *Ident, SourceLocation LBrace, const ParsedAttributesView &AttrList, - UsingDirectiveDecl *&UsingDecl); + UsingDirectiveDecl *&UsingDecl, + NamespaceDecl *PrevNS = nullptr); void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace); NamespaceDecl *getStdNamespace() const; @@ -9476,7 +9481,8 @@ void ActOnPragmaAttributeAttribute(ParsedAttr &Attribute, SourceLocation PragmaLoc, - attr::ParsedSubjectMatchRuleSet Rules); + attr::ParsedSubjectMatchRuleSet Rules, + bool WarnOnUnused); void ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc, const IdentifierInfo *Namespace); @@ -9715,7 +9721,75 @@ bool MightBeOdrUse); public: - /// Struct to store the context selectors info for declare variant directive. + /// Helper class to track the namespace, depth, and specializations for `omp + /// begin/end declare variant`. + class OMPDeclareVariantBeginEndTrackerTy { + /// The identifier used for the scope when `omp begin/end declare variant` + /// is lowered to an implicit namespace with `clang pragma push/pop` inside. + static constexpr StringRef OMPDeclVarScopeName = + "__omp_declare_variant_scope"; + + /// The prefix we use to "hide" variant functions (espc. for C). + static constexpr StringRef Prefix = "__"; + + /// The function variant we found in the current scope. + SmallVector FunctionVariants; + + /// The current (or last) namespace we used to "hide" variant code (espc. + /// for C++). + NamespaceDecl *NDecl = nullptr; + + /// The location where the last scope started. + SourceLocation Loc; + + /// The current nesting depth. + unsigned Depth = 0; + + /// Create an implicit function declaration matching \p FD which serves as + /// the base function for the specialization \p FD. + void createImplicitOpenMPVariantBase(Sema &S, FunctionDecl &FD); + + public: + /// Enter a new `begin/end declare variant` "scope". + void enter(Sema &S, SourceRange SR, ParsedAttributes *OMPAttrs, + OMPTraitInfo &TI); + + /// Exit the last `begin/end declare variant` "scope". + void exit(Sema &S, SourceLocation Loc); + + /// Remember \p FD as a variant which might require an implicit base. + void addVariantFunctionDefinition(FunctionDecl *FD) { + FunctionVariants.push_back(FD); + } + + /// Can we exit a scope at the moment. + bool canExitScope() { return Depth > 0; } + + /// Return the last namespace decleration (all ones used have the same + /// name). + NamespaceDecl *getNamespaceDecl() { return NDecl; } + + /// Return the name used for a variant function given a \p BaseName. + static std::string getNameForVariant(StringRef BaseName) { + return (Prefix + BaseName).str(); + } + + /// Return the name for the implicit base function given a \p VariantName. + static StringRef getNameForBase(StringRef VariantName) { + return VariantName.substr(Prefix.size()); + } + }; + + /// Object to keep track of `omp begin/end declare variant` contexts. + OMPDeclareVariantBeginEndTrackerTy OMPDeclareVariantBeginEndTracker; + + /// Handle a `omp begin declare variant`. + void ActOnOpenMPBeginDeclareVariant(SourceRange SR, + ParsedAttributes *OMPAttrs, + OMPTraitInfo &TI); + + /// Handle a `omp end declare variant`. + void ActOnOpenMPEndDeclareVariant(SourceLocation Loc); /// Checks if the variant/multiversion functions are compatible. bool areMultiversionVariantFunctionsCompatible( diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3096,6 +3096,8 @@ return MultiVersionKind::CPUDispatch; if (hasAttr()) return MultiVersionKind::CPUSpecific; + if (hasAttr()) + return MultiVersionKind::OpenMPVariant; return MultiVersionKind::None; } @@ -3111,6 +3113,11 @@ return isMultiVersion() && hasAttr(); } +bool FunctionDecl::isOpenMPVariantMultiVersion() const { + return isMultiVersion() && + getMultiVersionKind() == MultiVersionKind::OpenMPVariant; +} + void FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { redeclarable_base::setPreviousDecl(PrevDecl); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1013,6 +1013,16 @@ } } +static void AppendOpenMPVariantMangling(const CodeGenModule &CGM, + const FunctionDecl *FD, + raw_ostream &Out) { + for (auto *Attr : FD->specific_attrs()) { + (void)Attr; + // TODO: Mangle the name based on the context + llvm_unreachable("Declare variant mangling not implemented yet!"); + } +} + static std::string getMangledNameImpl(const CodeGenModule &CGM, GlobalDecl GD, const NamedDecl *ND, bool OmitMultiVersionMangling = false) { @@ -1053,6 +1063,9 @@ case MultiVersionKind::Target: AppendTargetMangling(CGM, FD->getAttr(), Out); break; + case MultiVersionKind::OpenMPVariant: + AppendOpenMPVariantMangling(CGM, FD, Out); + break; case MultiVersionKind::None: llvm_unreachable("None multiversion type isn't valid here"); } diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -1602,6 +1602,9 @@ AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed, DeclSpec::TST TagType, Decl *Tag) { assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); + auto *OMPAttrs = static_cast(Tok.getAnnotationValue()); + assert(OMPAttrs && + "Expected annotation value on `annot_pragma_openmp` token"); ParsingOpenMPDirectiveRAII DirScope(*this); ParenBraceBracketBalancer BalancerRAIIObj(*this); @@ -1772,8 +1775,12 @@ OMPContext OMPCtx(ASTCtx.getLangOpts().OpenMPIsDevice, ASTCtx.getTargetInfo().getTriple()); - if (isVariantApplicableInContext(VMI, OMPCtx)) + if (isVariantApplicableInContext(VMI, OMPCtx)) { + EnterScope(Scope::DeclScope); + SourceRange SR = SourceRange(Tok.getLastLoc(), Loc); + Actions.ActOnOpenMPBeginDeclareVariant(SR, OMPAttrs, TI); break; + } // Elide all the code till the matching end declare variant was found. unsigned Nesting = 1; @@ -1797,11 +1804,16 @@ return nullptr; break; } - case OMPD_end_declare_variant: - // FIXME: With the sema changes we will keep track of nesting and be able to - // diagnose unmatchend OMPD_end_declare_variant. + case OMPD_end_declare_variant: { + if (Actions.OMPDeclareVariantBeginEndTracker.canExitScope()) { + ExitScope(); + Actions.ActOnOpenMPEndDeclareVariant(Loc); + } else { + Diag(Loc, diag::err_expected_begin_declare_variant); + } ConsumeToken(); break; + } case OMPD_declare_variant: case OMPD_declare_simd: { // The syntax is: diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -158,9 +158,13 @@ }; struct PragmaOpenMPHandler : public PragmaHandler { - PragmaOpenMPHandler() : PragmaHandler("omp") { } + PragmaOpenMPHandler(AttributeFactory &AttrFactory) + : PragmaHandler("omp"), AttributesForPragmaOMPAttribute(AttrFactory) {} void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstToken) override; + + /// A pool of attributes that were parsed in \#pragma omp attributes. + ParsedAttributes AttributesForPragmaOMPAttribute; }; /// PragmaCommentHandler - "\#pragma comment ...". @@ -323,7 +327,7 @@ PP.AddPragmaHandler("OPENCL", FPContractHandler.get()); } if (getLangOpts().OpenMP) - OpenMPHandler = std::make_unique(); + OpenMPHandler = std::make_unique(AttrFactory); else OpenMPHandler = std::make_unique(); PP.AddPragmaHandler(OpenMPHandler.get()); @@ -1593,7 +1597,8 @@ Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace); Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc, - std::move(SubjectMatchRules)); + std::move(SubjectMatchRules), + /* WarnOnUnused */ true); } // #pragma GCC visibility comes in two variants: @@ -2240,6 +2245,7 @@ Tok.startToken(); Tok.setKind(tok::annot_pragma_openmp); Tok.setLocation(Introducer.Loc); + Tok.setAnnotationValue(static_cast(&AttributesForPragmaOMPAttribute)); while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) { Pragma.push_back(Tok); diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -650,9 +650,10 @@ } // end anonymous namespace -void Sema::ActOnPragmaAttributeAttribute( - ParsedAttr &Attribute, SourceLocation PragmaLoc, - attr::ParsedSubjectMatchRuleSet Rules) { +void Sema::ActOnPragmaAttributeAttribute(ParsedAttr &Attribute, + SourceLocation PragmaLoc, + attr::ParsedSubjectMatchRuleSet Rules, + bool WarnOnUnused) { Attribute.setIsPragmaClangAttribute(); SmallVector SubjectMatchRules; // Gather the subject match rules that are supported by the attribute. @@ -758,8 +759,9 @@ return; } - PragmaAttributeStack.back().Entries.push_back( - {PragmaLoc, &Attribute, std::move(SubjectMatchRules), /*IsUsed=*/false}); + PragmaAttributeStack.back().Entries.push_back({PragmaLoc, &Attribute, + std::move(SubjectMatchRules), + /*IsUsed=*/!WarnOnUnused}); } void Sema::ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2720,6 +2720,12 @@ // honored it. ++I; continue; + } else if (isa(NewAttribute) || + isa(NewAttribute)) { + // We allow to add OMPMultiVersionDeclare{Base/Variant}Attr to be added to + // declarations after defintions. + ++I; + continue; } S.Diag(NewAttribute->getLocation(), @@ -9965,6 +9971,10 @@ if (MVType != MultiVersionKind::Target) return true; break; + case attr::OMPMultiVersionDeclareVariant: + if (MVType != MultiVersionKind::OpenMPVariant) + return true; + break; default: return true; } @@ -10103,14 +10113,14 @@ // an analysis of all of them is a future FIXME. if (CausesMV && OldFD && HasNonMultiVersionAttributes(OldFD, MVType)) { S.Diag(OldFD->getLocation(), diag::err_multiversion_no_other_attrs) - << IsCPUSpecificCPUDispatchMVType; + << unsigned(MVType); S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); return true; } if (HasNonMultiVersionAttributes(NewFD, MVType)) return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs) - << IsCPUSpecificCPUDispatchMVType; + << unsigned(MVType); // Only allow transition to MultiVersion if it hasn't been used. if (OldFD && CausesMV && OldFD->isUsed(false)) @@ -10412,10 +10422,13 @@ const auto *NewTA = NewFD->getAttr(); const auto *NewCPUDisp = NewFD->getAttr(); const auto *NewCPUSpec = NewFD->getAttr(); + const auto *NewOpenMPVariant = + NewFD->getAttr(); + unsigned NumMV = bool(NewTA) + bool(NewCPUDisp) + bool(NewCPUSpec) + + bool(NewOpenMPVariant); // Mixing Multiversioning types is prohibited. - if ((NewTA && NewCPUDisp) || (NewTA && NewCPUSpec) || - (NewCPUDisp && NewCPUSpec)) { + if (NumMV > 1) { S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed); NewFD->setInvalidDecl(); return true; @@ -14434,17 +14447,28 @@ /*ErrorRecovery*/false); } + return CreateImplicitlyDefinedFunction( + Loc, SourceRange(), DeclaratorContext::BlockContext, II, BlockScope); +} + +FunctionDecl *Sema::CreateImplicitlyDefinedFunction(SourceLocation Loc, + SourceRange SR, + DeclaratorContext DC, + IdentifierInfo &II, + Scope *S) { // Set a Declarator for the implicit definition: int foo(); const char *Dummy; AttributeFactory attrFactory; DeclSpec DS(attrFactory); + DS.SetRangeStart(SR.getBegin()); + DS.SetRangeEnd(SR.getEnd()); unsigned DiagID; bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID, Context.getPrintingPolicy()); (void)Error; // Silence warning. assert(!Error && "Error setting up implicit decl!"); SourceLocation NoLoc; - Declarator D(DS, DeclaratorContext::BlockContext); + Declarator D(DS, DC); D.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/false, /*IsAmbiguous=*/false, /*LParenLoc=*/NoLoc, @@ -14467,7 +14491,7 @@ D.SetIdentifier(&II, Loc); // Insert this function into the enclosing block scope. - FunctionDecl *FD = cast(ActOnDeclarator(BlockScope, D)); + FunctionDecl *FD = cast(ActOnDeclarator(S, D)); FD->setImplicit(); AddKnownFunctionAttributes(FD); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6658,6 +6658,51 @@ D->addAttr(::new (S.Context) CFGuardAttr(S.Context, AL, Arg)); } +static void handleOMPMultiVersionDeclareBaseAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + if (D->hasAttr()) + return; + auto *OMPDeclBaseAttr = + static_cast(AL.getAttrPtr()); + D->addAttr(OMPDeclBaseAttr->clone(S.Context)); +} +static void handleOMPMultiVersionDeclareVariantAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + // Only apply `omp begin/end declare variant` to function definitions. + FunctionDecl *FD = dyn_cast(D); + if (!FD) + return; + + // The function definition is marked as multi-version and given the attribute + // that describes the OpenMP context selector. + auto *OMPDeclVariantExistingAttr = + FD->getAttr(); + if (OMPDeclVariantExistingAttr) { + // FIXME: Merge the context selector with an existing one. + S.Diag(AL.getLoc(), diag::warn_nested_declare_variant); + return; + } + + // Copy & add the OMPMultiVersionDeclareVariantAttr attribute. + auto *OMPDeclVariantAttr = + static_cast(AL.getAttrPtr()); + FD->addAttr(OMPDeclVariantAttr->clone(S.Context)); + + // Mark it multi-version as we can have multiple versions ;) + FD->setIsMultiVersion(true); + + // Rename it to avoid clashes (in C). + IdentifierInfo &VariangtII = S.getASTContext().Idents.get( + Sema::OMPDeclareVariantBeginEndTrackerTy::getNameForVariant( FD->getName())); + FD->setDeclName(DeclarationName(&VariangtII)); + + // We add a declaration to the global scope to pretend we do. This declaration + // is implicit and it is illigal to use it in any way. However, we rely on the + // fact that it is there initially so we can overwrite calls to this "base" + // with calls to the appropriate variant. + S.OMPDeclareVariantBeginEndTracker.addVariantFunctionDefinition(FD); +} + //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// @@ -7454,6 +7499,12 @@ case ParsedAttr::AT_UseHandle: handleHandleAttr(S, D, AL); break; + case ParsedAttr::AT_OMPMultiVersionDeclareBase: + handleOMPMultiVersionDeclareBaseAttr(S, D, AL); + break; + case ParsedAttr::AT_OMPMultiVersionDeclareVariant: + handleOMPMultiVersionDeclareVariantAttr(S, D, AL); + break; } } @@ -7690,6 +7741,26 @@ } } +namespace { +/// The `attribute push` matcher `function(is_definition)` needs to know if a +/// function declaration is a definition but we might check before the relevant +/// parts have been parsed. This RAII helper will set the `WillHaveBody` flag +/// if appropriate to make the matcher possible. +struct MarkDeclerationsForParamMatcherRAII { + FunctionDecl *FD; + bool OldWillHaveBody; + MarkDeclerationsForParamMatcherRAII(FunctionDecl *FD, const Declarator &PD) + : FD(FD), OldWillHaveBody(FD && FD->willHaveBody()) { + if (FD && PD.isFunctionDefinition()) + FD->setWillHaveBody(true); + } + ~MarkDeclerationsForParamMatcherRAII() { + if (FD) + FD->setWillHaveBody(OldWillHaveBody); + } +}; +} // namespace + /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in /// it, apply them to D. This is a bit tricky because PD can have attributes /// specified in many different places, and we need to find and apply them all. @@ -7710,7 +7781,10 @@ ProcessDeclAttributeList(S, D, PD.getAttributes()); // Apply additional attributes specified by '#pragma clang attribute'. - AddPragmaAttributes(S, D); + { + MarkDeclerationsForParamMatcherRAII MDFPM(dyn_cast(D), PD); + AddPragmaAttributes(S, D); + } } /// Is the given declaration allowed to use a forbidden type? diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -10503,7 +10503,8 @@ Decl *Sema::ActOnStartNamespaceDef( Scope *NamespcScope, SourceLocation InlineLoc, SourceLocation NamespaceLoc, SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace, - const ParsedAttributesView &AttrList, UsingDirectiveDecl *&UD) { + const ParsedAttributesView &AttrList, UsingDirectiveDecl *&UD, + NamespaceDecl *PrevNS) { SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; // For anonymous namespace, take the location of the left brace. SourceLocation Loc = II ? IdentLoc : LBrace; @@ -10513,7 +10514,6 @@ bool AddToKnown = false; Scope *DeclRegionScope = NamespcScope->getParent(); - NamespaceDecl *PrevNS = nullptr; if (II) { // C++ [namespace.def]p2: // The identifier in an original-namespace-definition shall not @@ -10529,9 +10529,11 @@ LookupResult R(*this, II, IdentLoc, LookupOrdinaryName, ForExternalRedeclaration); LookupQualifiedName(R, CurContext->getRedeclContext()); + NamedDecl *PrevDecl = R.isSingleResult() ? R.getRepresentativeDecl() : nullptr; - PrevNS = dyn_cast_or_null(PrevDecl); + if (auto *PrevDeclNS = dyn_cast_or_null(PrevDecl)) + PrevNS = PrevDeclNS; if (PrevNS) { // This is an extended namespace definition. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5704,6 +5704,84 @@ } } +/// Given the expression \p Fn that is the callee expression for a to be build +/// call, determine if there is a specialization via the OpenMP declare variant +/// mechanism available. If there is, return the specialized callee expression, +/// otherwise return \p Fn. +static ExprResult specializeOpenMPCallee(Sema &S, ExprResult Call, Scope *Scope, + Expr *Fn, SourceLocation LParenLoc, + MultiExprArg ArgExprs, + SourceLocation RParenLoc, + Expr *ExecConfig) { + // The common case is a regular call we do not want to specialize at all. Try + // to make that case fast by bailing early. + NamespaceDecl *NDecl = S.OMPDeclareVariantBeginEndTracker.getNamespaceDecl(); + if (!NDecl) + return Call; + + CallExpr *CE = dyn_cast(Call.get()); + if (!CE) + return Call; + + FunctionDecl *CalleeFnDecl = CE->getDirectCallee(); + if (!CalleeFnDecl) + return Call; + + auto *OMPBaseAttr = CalleeFnDecl->getAttr(); + if (!OMPBaseAttr) + return Call; + + UnqualifiedId FnName; + std::string Name = + Sema::OMPDeclareVariantBeginEndTrackerTy::getNameForVariant( + CalleeFnDecl->getIdentifier()->getName()); + FnName.setIdentifier(&S.Context.Idents.get(Name), SourceLocation()); + FnName.setKind(UnqualifiedIdKind::IK_Identifier); + + SourceLocation TemplateKWLoc; + CXXScopeSpec FnScopeSpec; + FnScopeSpec.Extend(S.getASTContext(), NDecl, NDecl->getLocation(), + SourceLocation()); + ExprResult OMPVariantRes = + S.ActOnIdExpression(Scope, FnScopeSpec, TemplateKWLoc, FnName, + /*HasTrailingLParen=*/true, + /*IsAddressOfOperand=*/false); + if (!OMPVariantRes.isUsable()) + return Call; + + ExprResult NewCall = S.BuildCallExpr(Scope, OMPVariantRes.get(), LParenLoc, + ArgExprs, RParenLoc, ExecConfig); + if (!NewCall.isUsable()) + return Call; + + CallExpr *NewCE = dyn_cast(NewCall.get()); + if (!NewCE) + return Call; + + FunctionDecl *NewCalleeFnDecl = NewCE->getDirectCallee(); + if (!NewCalleeFnDecl) + return Call; + + OMPMultiVersionDeclareVariantAttr *VariantAttr = + NewCalleeFnDecl->getAttr(); + if (!VariantAttr) + return Call; + assert(VariantAttr && "Lookup of OpenMP declare variant specialization " + "returned non specialized function."); + + VariantMatchInfo VMI; + OMPTraitInfo &TI = VariantAttr->getTraitInfo(); + TI.getAsVariantMatchInfo(S.getASTContext(), VMI, /* DeviceSetOnly */ false); + + OMPContext OMPCtx(S.getLangOpts().OpenMPIsDevice, + S.getASTContext().getTargetInfo().getTriple()); + + if (!isVariantApplicableInContext(VMI, OMPCtx)) + return Call; + + return NewCall; +} + ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig) { @@ -5724,6 +5802,10 @@ } } + if (LangOpts.OpenMP) + Call = specializeOpenMPCallee(*this, Call, Scope, Fn, LParenLoc, ArgExprs, + RParenLoc, ExecConfig); + return Call; } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1988,6 +1988,9 @@ else if (NameKind == LookupObjCImplicitSelfParam && !isa(*I)) continue; + else if (S->getEntity() && llvm::isa(S->getEntity()) && + !S->getEntity()->containsDecl(D)) + continue; R.addDecl(D); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -2208,6 +2208,97 @@ void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; } +const StringRef Sema::OMPDeclareVariantBeginEndTrackerTy::OMPDeclVarScopeName; +const StringRef Sema::OMPDeclareVariantBeginEndTrackerTy::Prefix; + +void Sema::OMPDeclareVariantBeginEndTrackerTy::createImplicitOpenMPVariantBase( + Sema &S, FunctionDecl &FD) { + // Undo the renaming we did for the variant and create an implicit + // declaration with the OMPMultiVersionDeclareBaseAttr to indicate it is a + // starting point for OpenMP specialization. + SourceRange SR = FD.getSourceRange(); + IdentifierInfo *II = &S.getASTContext().Idents.get( + OMPDeclareVariantBeginEndTrackerTy::getNameForBase(FD.getName())); + FunctionDecl *BaseFD = S.CreateImplicitlyDefinedFunction( + FD.getLocation(), SR, DeclaratorContext::FileContext, *II, + S.getCurScope()); + + if (!BaseFD->hasAttr()) + BaseFD->addAttr( + OMPMultiVersionDeclareBaseAttr::CreateImplicit(S.getASTContext(), SR)); +} + +void Sema::OMPDeclareVariantBeginEndTrackerTy::enter(Sema &S, SourceRange SR, + ParsedAttributes *OMPAttrs, + OMPTraitInfo &TI) { + // Keep track of the nesting depth, start a new implicit namespace to + // encapuslate the code and emulate an `clang attribute push` with the + // `OMPMultiVersionDeclareVariantAttr` attribute. + ++Depth; + + ASTContext &Ctx = S.getASTContext(); + auto &OMPDeclVarScopeII = Ctx.Idents.get(OMPDeclVarScopeName); + + ParsedAttributesView Attrs; + UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; + SourceLocation Loc = SR.getBegin(); + + NDecl = dyn_cast(S.ActOnStartNamespaceDef( + S.getCurScope(), SourceLocation(), Loc, Loc, &OMPDeclVarScopeII, Loc, + Attrs, ImplicitUsingDirectiveDecl, NDecl)); + + S.ActOnPragmaAttributeEmptyPush(Loc, &OMPDeclVarScopeII); + + // The OMPMultiVersionDeclareVariantAttr attribute will be applied to all + // function definitions. + attr::ParsedSubjectMatchRuleSet SubjectMatchRules; + SubjectMatchRules + [attr::SubjectMatchRule::SubjectMatchRule_function_is_definition] = SR; + Attr *A = OMPMultiVersionDeclareVariantAttr::Create(Ctx, TI, SR); + + auto &AttrSpellingII = Ctx.Idents.get(A->getSpelling()); + ParsedAttr *PA = OMPAttrs->addNewAttrPtrAttr( + &AttrSpellingII, SR, nullptr, Loc, A, + ParsedAttr::Kind::AT_OMPMultiVersionDeclareVariant, + ParsedAttr::AS_Pragma); + S.ActOnPragmaAttributeAttribute(*PA, Loc, std::move(SubjectMatchRules), + /* WarnOnUnused */ false); + assert(PA->isPragmaClangAttribute() && "expected #pragma clang attribute"); +} + +void Sema::ActOnOpenMPBeginDeclareVariant(SourceRange SR, + ParsedAttributes *OMPAttrs, + OMPTraitInfo &TI) { + OMPDeclareVariantBeginEndTracker.enter(*this, SR, OMPAttrs, TI); +} + +void Sema::OMPDeclareVariantBeginEndTrackerTy::exit(Sema &S, + SourceLocation Loc) { + assert(canExitScope() && "Cannot call exit without a scpoe to exit!"); + --Depth; + + // If this was the outermost `omp begin declare variant` we emulate `clang + // attribute pop` and close the implicit namespace. + auto &OMPDeclVarScopeII = S.getASTContext().Idents.get(OMPDeclVarScopeName); + S.ActOnPragmaAttributePop(Loc, &OMPDeclVarScopeII); + + S.ActOnFinishNamespaceDef(NDecl, Loc); + + DeclGroupPtrTy Decl = S.ConvertDeclToDeclGroup(NDecl, nullptr); + S.ActOnDeclStmt(Decl, NDecl->getLocation(), Loc); + + // Finally, create implicit declarations for all function variants outside the + // implicit namespace. Calls to them, or any redeclaration, will be candidates + // for variant specialization. + for (FunctionDecl *FD : FunctionVariants) + createImplicitOpenMPVariantBase(S, *FD); + FunctionVariants.clear(); +} + +void Sema::ActOnOpenMPEndDeclareVariant(SourceLocation Loc) { + OMPDeclareVariantBeginEndTracker.exit(*this, Loc); +} + void Sema::finalizeOpenMPDelayedAnalysis() { assert(LangOpts.OpenMP && "Expected OpenMP compilation mode."); // Diagnose implicit declare target functions and their callees. diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -9372,10 +9372,58 @@ return Comparison::Equal; } -static bool isBetterMultiversionCandidate(const OverloadCandidate &Cand1, +static const OverloadCandidate * +getBetterOpenMPMultiversionCandidate(ASTContext &ASTCtx, + const OverloadCandidate &Cand1, + const OverloadCandidate &Cand2) { + MultiVersionKind MK1 = Cand1.Function->getMultiVersionKind(); + MultiVersionKind MK2 = Cand2.Function->getMultiVersionKind(); + bool Cand1IsOpenMPVariant = MK1 == MultiVersionKind::OpenMPVariant; + bool Cand2IsOpenMPVariant = MK2 == MultiVersionKind::OpenMPVariant; + if (!Cand1IsOpenMPVariant && !Cand2IsOpenMPVariant) + return nullptr; + OMPMultiVersionDeclareVariantAttr *OMPSDVA1 = + Cand1.Function->getAttr(); + OMPMultiVersionDeclareVariantAttr *OMPSDVA2 = + Cand2.Function->getAttr(); + + SmallVector VMIs(2); + llvm::omp::VariantMatchInfo &VMI1 = VMIs[0], &VMI2 = VMIs[1]; + llvm::omp::OMPContext OMPCtx(ASTCtx.getLangOpts().OpenMPIsDevice, + ASTCtx.getTargetInfo().getTriple()); + + bool Cand1IsApplicable = !OMPSDVA1; + if (OMPSDVA1) { + OMPSDVA1->getTraitInfo().getAsVariantMatchInfo(ASTCtx, VMI1, + /* DeviceSetOnly */ false); + Cand1IsApplicable = llvm::omp::isVariantApplicableInContext(VMI1, OMPCtx); + } + bool Cand2IsApplicable = !OMPSDVA2; + if (OMPSDVA2) { + OMPSDVA2->getTraitInfo().getAsVariantMatchInfo(ASTCtx, VMI2, + /* DeviceSetOnly */ false); + Cand2IsApplicable = llvm::omp::isVariantApplicableInContext(VMI2, OMPCtx); + } + if (!Cand1IsApplicable) + return &Cand2; + if (!Cand2IsApplicable) + return &Cand1; + int BestIdx = llvm::omp::getBestVariantMatchForContext(VMIs, OMPCtx); + if (BestIdx < 0) + return nullptr; + assert((BestIdx == 0 || BestIdx == 1) && + "Expected an index matching the given selection."); + return BestIdx ? &Cand2 : &Cand1; +} + +static bool isBetterMultiversionCandidate(ASTContext &ASTCtx, + const OverloadCandidate &Cand1, const OverloadCandidate &Cand2) { - if (!Cand1.Function || !Cand1.Function->isMultiVersion() || !Cand2.Function || - !Cand2.Function->isMultiVersion()) + if (!Cand1.Function || !Cand2.Function) + return false; + bool Cand1IsMultiVersion = Cand1.Function->isMultiVersion(); + bool Cand2IsMultiVersion = Cand2.Function->isMultiVersion(); + if (!Cand1IsMultiVersion && !Cand2IsMultiVersion) return false; // If Cand1 is invalid, it cannot be a better match, if Cand2 is invalid, this @@ -9383,6 +9431,13 @@ if (Cand1.Function->isInvalidDecl()) return false; if (Cand2.Function->isInvalidDecl()) return true; + if (const OverloadCandidate *OC = + getBetterOpenMPMultiversionCandidate(ASTCtx, Cand1, Cand2)) + return OC == &Cand1; + + if (!Cand1IsMultiVersion || !Cand2IsMultiVersion) + return false; + // If this is a cpu_dispatch/cpu_specific multiversion situation, prefer // cpu_dispatch, else arbitrarily based on the identifiers. bool Cand1CPUDisp = Cand1.Function->hasAttr(); @@ -9677,7 +9732,7 @@ if (HasPS1 != HasPS2 && HasPS1) return true; - return isBetterMultiversionCandidate(Cand1, Cand2); + return isBetterMultiversionCandidate(S.getASTContext(), Cand1, Cand2); } /// Determine whether two declarations are "equivalent" for the purposes of diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant.c deleted file mode 100644 --- a/clang/test/AST/ast-dump-openmp-begin-declare-variant.c +++ /dev/null @@ -1,55 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -ast-dump %s | FileCheck %s - -#pragma omp begin declare variant match(device={kind(cpu)}) -int also_before(void) { - return 0; -} -#pragma omp end declare variant - -#pragma omp begin declare variant match(device={kind(gpu)}) -int also_after(void) { - return 2; -} -int also_before(void) { - return 2; -} -#pragma omp end declare variant - - -#pragma omp begin declare variant match(device={kind(fpga)}) - -This text is never parsed! - -#pragma omp end declare variant - -int also_after(void) { - return 0; -} - -int test() { - return also_after() + also_before(); -} - -// Make sure: -// - we do see the ast nodes for the cpu kind -// - we do not see the ast nodes for the gpu kind -// - we do not choke on the text in the kind(fpga) guarded scope. - -// CHECK: -FunctionDecl {{.*}} <{{.*}}4:1, line:{{.*}}:1> line:{{.*}}:5 used also_before 'int (void)' -// CHECK-NEXT: -CompoundStmt {{.*}} -// CHECK-NEXT: `-ReturnStmt {{.*}} -// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 0 -// CHECK-NEXT: -FunctionDecl {{.*}} line:{{.*}}:5 used also_after 'int (void)' -// CHECK-NEXT: -CompoundStmt {{.*}} -// CHECK-NEXT: `-ReturnStmt {{.*}} -// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 0 -// CHECK-NEXT: `-FunctionDecl {{.*}} line:{{.*}}:5 test 'int ()' -// CHECK-NEXT: `-CompoundStmt {{.*}} -// CHECK-NEXT: `-ReturnStmt {{.*}} -// CHECK-NEXT: `-BinaryOperator {{.*}} 'int' '+' -// CHECK-NEXT: |-CallExpr {{.*}} 'int' -// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'int (*)(void)' -// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'int (void)' Function {{.*}} 'also_after' 'int (void)' -// CHECK-NEXT: `-CallExpr {{.*}} 'int' -// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int (*)(void)' -// CHECK-NEXT: `-DeclRefExpr {{.*}} 'int (void)' Function {{.*}} 'also_before' 'int (void)' diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_1.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_1.c new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_1.c @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s +// expected-no-diagnostics + +int also_before(void) { + return 0; +} + +#pragma omp begin declare variant match(device={kind(gpu)}) +int also_after(void) { + return 1; +} +int also_before(void) { + return 2; +} +#pragma omp end declare variant + + +#pragma omp begin declare variant match(device={kind(fpga)}) + +This text is never parsed! + +#pragma omp end declare variant + +int also_after(void) { + return 0; +} + +int test() { + // Should return 0. + return also_after() + also_before(); +} + +// Make sure: +// - we do not see the ast nodes for the gpu kind +// - we do not choke on the text in the kind(fpga) guarded scopes + +// CHECK: |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})' +// CHECK-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] +// CHECK-NEXT: | `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] +// CHECK-NEXT: | `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: |-FunctionDecl [[ADDR_4:0x[a-z0-9]*]] line:25:5 used also_after 'int ({{.*}})' +// CHECK-NEXT: | `-CompoundStmt [[ADDR_5:0x[a-z0-9]*]] +// CHECK-NEXT: | `-ReturnStmt [[ADDR_6:0x[a-z0-9]*]] +// CHECK-NEXT: | `-IntegerLiteral [[ADDR_7:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: `-FunctionDecl [[ADDR_8:0x[a-z0-9]*]] line:29:5 test 'int ({{.*}})' +// CHECK-NEXT: `-CompoundStmt [[ADDR_9:0x[a-z0-9]*]] +// CHECK-NEXT: `-ReturnStmt [[ADDR_10:0x[a-z0-9]*]] +// CHECK-NEXT: `-BinaryOperator [[ADDR_11:0x[a-z0-9]*]] 'int' '+' +// CHECK-NEXT: |-CallExpr [[ADDR_12:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | `-ImplicitCastExpr [[ADDR_13:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CHECK-NEXT: | `-DeclRefExpr [[ADDR_14:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_4]] 'also_after' 'int ({{.*}})' +// CHECK-NEXT: `-CallExpr [[ADDR_15:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: `-ImplicitCastExpr [[ADDR_16:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CHECK-NEXT: `-DeclRefExpr [[ADDR_17:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_0]] 'also_before' 'int ({{.*}})' diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_2.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_2.c new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_2.c @@ -0,0 +1,76 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s +// expected-no-diagnostics + +#pragma omp begin declare variant match(device={kind(cpu)}) +int also_before(void) { + return 0; +} +#pragma omp end declare variant + +#pragma omp begin declare variant match(implementation={vendor(score(100):llvm)}) +int also_after(void) { + return 0; +} +#pragma omp end declare variant +#pragma omp begin declare variant match(implementation={vendor(score(0):llvm)}) +int also_before(void) { + return 1; +} +#pragma omp end declare variant + +int also_after(void) { + return 2; +} + +int test() { + // Should return 0. + return also_after() + also_before(); +} + +// Make sure: +// - we do see the ast nodes for the cpu kind +// - we do see the ast nodes for the llvm vendor +// - we pick the right callees + +// CHECK: |-NamespaceDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:9:1> line:5:60 __omp_declare_variant_scope +// CHECK-NEXT: | `-FunctionDecl [[ADDR_1:0x[a-z0-9]*]] line:6:5 used __also_before 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_2:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_3:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_4:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_5:0x[a-z0-9]*]] device={kind(cpu)} +// CHECK-NEXT: |-FunctionDecl [[ADDR_6:0x[a-z0-9]*]] line:6:5 implicit used also_before 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_7:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-NamespaceDecl [[ADDR_8:0x[a-z0-9]*]] prev [[ADDR_0]] line:11:82 __omp_declare_variant_scope +// CHECK-NEXT: | |-original Namespace [[ADDR_0]] '__omp_declare_variant_scope' +// CHECK-NEXT: | `-FunctionDecl [[ADDR_9:0x[a-z0-9]*]] line:12:5 used __also_after 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_10:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_11:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_12:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_13:0x[a-z0-9]*]] implementation={vendor(score(100): llvm)} +// CHECK-NEXT: |-FunctionDecl [[ADDR_14:0x[a-z0-9]*]] line:12:5 implicit used also_after 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_15:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-NamespaceDecl [[ADDR_16:0x[a-z0-9]*]] prev [[ADDR_8]] line:16:80 __omp_declare_variant_scope +// CHECK-NEXT: | |-original Namespace [[ADDR_0]] '__omp_declare_variant_scope' +// CHECK-NEXT: | `-FunctionDecl [[ADDR_17:0x[a-z0-9]*]] line:17:5 __also_before 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_18:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_19:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_20:0x[a-z0-9]*]] 'int' 1 +// CHECK-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_21:0x[a-z0-9]*]] implementation={vendor(score(0): llvm)} +// CHECK-NEXT: |-FunctionDecl [[ADDR_22:0x[a-z0-9]*]] prev [[ADDR_6]] line:17:5 implicit used also_before 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_23:0x[a-z0-9]*]] Inherited Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_24:0x[a-z0-9]*]] prev [[ADDR_14]] line:22:5 used also_after 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_25:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_26:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_27:0x[a-z0-9]*]] 'int' 2 +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_28:0x[a-z0-9]*]] Inherited Implicit +// CHECK-NEXT: `-FunctionDecl [[ADDR_29:0x[a-z0-9]*]] line:26:5 test 'int ({{.*}})' +// CHECK-NEXT: `-CompoundStmt [[ADDR_30:0x[a-z0-9]*]] +// CHECK-NEXT: `-ReturnStmt [[ADDR_31:0x[a-z0-9]*]] +// CHECK-NEXT: `-BinaryOperator [[ADDR_32:0x[a-z0-9]*]] 'int' '+' +// CHECK-NEXT: |-CallExpr [[ADDR_33:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | `-ImplicitCastExpr [[ADDR_34:0x[a-z0-9]*]] > 'int (*)({{.*}})' +// CHECK-NEXT: | `-DeclRefExpr [[ADDR_35:0x[a-z0-9]*]] > 'int ({{.*}})' {{.*}}Function [[ADDR_9]] '__also_after' 'int ({{.*}})' +// CHECK-NEXT: `-CallExpr [[ADDR_36:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: `-ImplicitCastExpr [[ADDR_37:0x[a-z0-9]*]] > 'int (*)({{.*}})' +// CHECK-NEXT: `-DeclRefExpr [[ADDR_38:0x[a-z0-9]*]] > 'int ({{.*}})' {{.*}}Function [[ADDR_1]] '__also_before' 'int ({{.*}})' diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_3.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_3.c new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_3.c @@ -0,0 +1,76 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s +// expected-no-diagnostics + +#pragma omp begin declare variant match(device={kind(cpu)}) +int also_before(void) { + return 1; +} +#pragma omp end declare variant + +#pragma omp begin declare variant match(implementation={vendor(score(0):llvm)}) +int also_after(void) { + return 0; +} +#pragma omp end declare variant +#pragma omp begin declare variant match(implementation={vendor(score(100):llvm)}) +int also_before(void) { + return 0; +} +#pragma omp end declare variant + +int also_after(void) { + return 2; +} + +int test() { + // Should return 0. + return also_after() + also_before(); +} + +// Make sure: +// - we do see the ast nodes for the cpu kind +// - we do see the ast nodes for the llvm vendor +// - we pick the right callees + +// CHECK: |-NamespaceDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:9:1> line:5:60 __omp_declare_variant_scope +// CHECK-NEXT: | `-FunctionDecl [[ADDR_1:0x[a-z0-9]*]] line:6:5 __also_before 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_2:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_3:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_4:0x[a-z0-9]*]] 'int' 1 +// CHECK-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_5:0x[a-z0-9]*]] device={kind(cpu)} +// CHECK-NEXT: |-FunctionDecl [[ADDR_6:0x[a-z0-9]*]] line:6:5 implicit used also_before 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_7:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-NamespaceDecl [[ADDR_8:0x[a-z0-9]*]] prev [[ADDR_0]] line:11:80 __omp_declare_variant_scope +// CHECK-NEXT: | |-original Namespace [[ADDR_0]] '__omp_declare_variant_scope' +// CHECK-NEXT: | `-FunctionDecl [[ADDR_9:0x[a-z0-9]*]] line:12:5 used __also_after 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_10:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_11:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_12:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_13:0x[a-z0-9]*]] implementation={vendor(score(0): llvm)} +// CHECK-NEXT: |-FunctionDecl [[ADDR_14:0x[a-z0-9]*]] line:12:5 implicit used also_after 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_15:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-NamespaceDecl [[ADDR_16:0x[a-z0-9]*]] prev [[ADDR_8]] line:16:82 __omp_declare_variant_scope +// CHECK-NEXT: | |-original Namespace [[ADDR_0]] '__omp_declare_variant_scope' +// CHECK-NEXT: | `-FunctionDecl [[ADDR_17:0x[a-z0-9]*]] line:17:5 used __also_before 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_18:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_19:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_20:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_21:0x[a-z0-9]*]] implementation={vendor(score(100): llvm)} +// CHECK-NEXT: |-FunctionDecl [[ADDR_22:0x[a-z0-9]*]] prev [[ADDR_6]] line:17:5 implicit used also_before 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_23:0x[a-z0-9]*]] Inherited Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_24:0x[a-z0-9]*]] prev [[ADDR_14]] line:22:5 used also_after 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_25:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_26:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_27:0x[a-z0-9]*]] 'int' 2 +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_28:0x[a-z0-9]*]] Inherited Implicit +// CHECK-NEXT: `-FunctionDecl [[ADDR_29:0x[a-z0-9]*]] line:26:5 test 'int ({{.*}})' +// CHECK-NEXT: `-CompoundStmt [[ADDR_30:0x[a-z0-9]*]] +// CHECK-NEXT: `-ReturnStmt [[ADDR_31:0x[a-z0-9]*]] +// CHECK-NEXT: `-BinaryOperator [[ADDR_32:0x[a-z0-9]*]] 'int' '+' +// CHECK-NEXT: |-CallExpr [[ADDR_33:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | `-ImplicitCastExpr [[ADDR_34:0x[a-z0-9]*]] > 'int (*)({{.*}})' +// CHECK-NEXT: | `-DeclRefExpr [[ADDR_35:0x[a-z0-9]*]] > 'int ({{.*}})' {{.*}}Function [[ADDR_9]] '__also_after' 'int ({{.*}})' +// CHECK-NEXT: `-CallExpr [[ADDR_36:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: `-ImplicitCastExpr [[ADDR_37:0x[a-z0-9]*]] > 'int (*)({{.*}})' +// CHECK-NEXT: `-DeclRefExpr [[ADDR_38:0x[a-z0-9]*]] > 'int ({{.*}})' {{.*}}Function [[ADDR_17]] '__also_before' 'int ({{.*}})' diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_4.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_4.c new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_4.c @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s +// expected-no-diagnostics + +#pragma omp begin declare variant match(device={kind(cpu)}) +int also_before(void) { + return 0; +} +#pragma omp end declare variant + +int also_after(void) { + return 0; +} + +int test() { + // Should return 0. + return also_after() + also_before(); +} + +// Make sure: +// - we do see the ast nodes for the cpu kind +// - we pick the right callees + +// CHECK: |-NamespaceDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:9:1> line:5:60 __omp_declare_variant_scope +// CHECK-NEXT: | `-FunctionDecl [[ADDR_1:0x[a-z0-9]*]] line:6:5 used __also_before 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_2:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_3:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_4:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_5:0x[a-z0-9]*]] device={kind(cpu)} +// CHECK-NEXT: |-FunctionDecl [[ADDR_6:0x[a-z0-9]*]] line:6:5 implicit used also_before 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_7:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_8:0x[a-z0-9]*]] line:11:5 used also_after 'int ({{.*}})' +// CHECK-NEXT: | `-CompoundStmt [[ADDR_9:0x[a-z0-9]*]] +// CHECK-NEXT: | `-ReturnStmt [[ADDR_10:0x[a-z0-9]*]] +// CHECK-NEXT: | `-IntegerLiteral [[ADDR_11:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: `-FunctionDecl [[ADDR_12:0x[a-z0-9]*]] line:15:5 test 'int ({{.*}})' +// CHECK-NEXT: `-CompoundStmt [[ADDR_13:0x[a-z0-9]*]] +// CHECK-NEXT: `-ReturnStmt [[ADDR_14:0x[a-z0-9]*]] +// CHECK-NEXT: `-BinaryOperator [[ADDR_15:0x[a-z0-9]*]] 'int' '+' +// CHECK-NEXT: |-CallExpr [[ADDR_16:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | `-ImplicitCastExpr [[ADDR_17:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CHECK-NEXT: | `-DeclRefExpr [[ADDR_18:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_8]] 'also_after' 'int ({{.*}})' +// CHECK-NEXT: `-CallExpr [[ADDR_19:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: `-ImplicitCastExpr [[ADDR_20:0x[a-z0-9]*]] > 'int (*)({{.*}})' +// CHECK-NEXT: `-DeclRefExpr [[ADDR_21:0x[a-z0-9]*]] > 'int ({{.*}})' {{.*}}Function [[ADDR_1]] '__also_before' 'int ({{.*}})' diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_5.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_5.c new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_5.c @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s +// expected-no-diagnostics + +int also_before(void) { + return 1; +} + +#pragma omp begin declare variant match(implementation={vendor(llvm)}) +int also_after(void) { + return 0; +} +int also_before(void) { + return 0; +} +#pragma omp end declare variant + +int also_after(void) { + return 2; +} + +int main() { + // Should return 0. + return (also_after)() + + (also_before)() + + (&also_after)() + + (&also_before)(); +} + +// Make sure: +// - we see the specialization in the AST +// - we pick the right callees + +// CHECK: |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})' +// CHECK-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] +// CHECK-NEXT: | `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] +// CHECK-NEXT: | `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] 'int' 1 +// CHECK-NEXT: |-NamespaceDecl [[ADDR_4:0x[a-z0-9]*]] line:9:71 __omp_declare_variant_scope +// CHECK-NEXT: | |-FunctionDecl [[ADDR_5:0x[a-z0-9]*]] line:10:5 used __also_after 'int ({{.*}})' +// CHECK-NEXT: | | |-CompoundStmt [[ADDR_6:0x[a-z0-9]*]] +// CHECK-NEXT: | | | `-ReturnStmt [[ADDR_7:0x[a-z0-9]*]] +// CHECK-NEXT: | | | `-IntegerLiteral [[ADDR_8:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: | | `-OMPMultiVersionDeclareVariantAttr [[ADDR_9:0x[a-z0-9]*]] implementation={vendor(llvm)} +// CHECK-NEXT: | `-FunctionDecl [[ADDR_10:0x[a-z0-9]*]] line:13:5 used __also_before 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_11:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_12:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_13:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_14:0x[a-z0-9]*]] implementation={vendor(llvm)} +// CHECK-NEXT: |-FunctionDecl [[ADDR_15:0x[a-z0-9]*]] line:10:5 implicit used also_after 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_16:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_17:0x[a-z0-9]*]] prev [[ADDR_0]] line:13:5 implicit used also_before 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_18:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_19:0x[a-z0-9]*]] prev [[ADDR_15]] line:18:5 used also_after 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_20:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_21:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_22:0x[a-z0-9]*]] 'int' 2 +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_23:0x[a-z0-9]*]] Inherited Implicit +// CHECK-NEXT: `-FunctionDecl [[ADDR_24:0x[a-z0-9]*]] line:22:5 main 'int ({{.*}})' +// CHECK-NEXT: `-CompoundStmt [[ADDR_25:0x[a-z0-9]*]] +// CHECK-NEXT: `-ReturnStmt [[ADDR_26:0x[a-z0-9]*]] +// CHECK-NEXT: `-BinaryOperator [[ADDR_27:0x[a-z0-9]*]] 'int' '+' +// CHECK-NEXT: |-BinaryOperator [[ADDR_28:0x[a-z0-9]*]] 'int' '+' +// CHECK-NEXT: | |-BinaryOperator [[ADDR_29:0x[a-z0-9]*]] 'int' '+' +// CHECK-NEXT: | | |-CallExpr [[ADDR_30:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | | | `-ImplicitCastExpr [[ADDR_31:0x[a-z0-9]*]] > 'int (*)({{.*}})' +// CHECK-NEXT: | | | `-DeclRefExpr [[ADDR_32:0x[a-z0-9]*]] > 'int ({{.*}})' {{.*}}Function [[ADDR_5]] '__also_after' 'int ({{.*}})' +// CHECK-NEXT: | | `-CallExpr [[ADDR_33:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | | `-ImplicitCastExpr [[ADDR_34:0x[a-z0-9]*]] > 'int (*)({{.*}})' +// CHECK-NEXT: | | `-DeclRefExpr [[ADDR_35:0x[a-z0-9]*]] > 'int ({{.*}})' {{.*}}Function [[ADDR_10]] '__also_before' 'int ({{.*}})' +// CHECK-NEXT: | `-CallExpr [[ADDR_36:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | `-ImplicitCastExpr [[ADDR_37:0x[a-z0-9]*]] > 'int (*)({{.*}})' +// CHECK-NEXT: | `-DeclRefExpr [[ADDR_38:0x[a-z0-9]*]] > 'int ({{.*}})' {{.*}}Function [[ADDR_5]] '__also_after' 'int ({{.*}})' +// CHECK-NEXT: `-CallExpr [[ADDR_39:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: `-ImplicitCastExpr [[ADDR_40:0x[a-z0-9]*]] > 'int (*)({{.*}})' +// CHECK-NEXT: `-DeclRefExpr [[ADDR_41:0x[a-z0-9]*]] > 'int ({{.*}})' {{.*}}Function [[ADDR_10]] '__also_before' 'int ({{.*}})' diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_6.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_6.c new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_6.c @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s +// expected-no-diagnostics + +int also_before(void) { + return 0; +} + +#pragma omp begin declare variant match(implementation={vendor(ibm)}) +int also_after(void) { + return 1; +} +int also_before(void) { + return 2; +} +#pragma omp end declare variant + +int also_after(void) { + return 0; +} + +int main() { + // Should return 0. + return also_after() + also_before(); +} + +// Make sure: +// - we see the specialization in the AST +// - we do use the original pointers for the calls as the variants are not applicable (this is not the ibm compiler). + +// CHECK: |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})' +// CHECK-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] +// CHECK-NEXT: | `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] +// CHECK-NEXT: | `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: |-NamespaceDecl [[ADDR_4:0x[a-z0-9]*]] line:9:70 __omp_declare_variant_scope +// CHECK-NEXT: | |-FunctionDecl [[ADDR_5:0x[a-z0-9]*]] line:10:5 used __also_after 'int ({{.*}})' +// CHECK-NEXT: | | |-CompoundStmt [[ADDR_6:0x[a-z0-9]*]] +// CHECK-NEXT: | | | `-ReturnStmt [[ADDR_7:0x[a-z0-9]*]] +// CHECK-NEXT: | | | `-IntegerLiteral [[ADDR_8:0x[a-z0-9]*]] 'int' 1 +// CHECK-NEXT: | | `-OMPMultiVersionDeclareVariantAttr [[ADDR_9:0x[a-z0-9]*]] implementation={vendor(ibm)} +// CHECK-NEXT: | `-FunctionDecl [[ADDR_10:0x[a-z0-9]*]] line:13:5 used __also_before 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_11:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_12:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_13:0x[a-z0-9]*]] 'int' 2 +// CHECK-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_14:0x[a-z0-9]*]] implementation={vendor(ibm)} +// CHECK-NEXT: |-FunctionDecl [[ADDR_15:0x[a-z0-9]*]] line:10:5 implicit used also_after 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_16:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_17:0x[a-z0-9]*]] prev [[ADDR_0]] line:13:5 implicit used also_before 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_18:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_19:0x[a-z0-9]*]] prev [[ADDR_15]] line:18:5 used also_after 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_20:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_21:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_22:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_23:0x[a-z0-9]*]] Inherited Implicit +// CHECK-NEXT: `-FunctionDecl [[ADDR_24:0x[a-z0-9]*]] line:22:5 main 'int ({{.*}})' +// CHECK-NEXT: `-CompoundStmt [[ADDR_25:0x[a-z0-9]*]] +// CHECK-NEXT: `-ReturnStmt [[ADDR_26:0x[a-z0-9]*]] +// CHECK-NEXT: `-BinaryOperator [[ADDR_27:0x[a-z0-9]*]] 'int' '+' +// CHECK-NEXT: |-CallExpr [[ADDR_28:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | `-ImplicitCastExpr [[ADDR_29:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CHECK-NEXT: | `-DeclRefExpr [[ADDR_30:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_19]] 'also_after' 'int ({{.*}})' +// CHECK-NEXT: `-CallExpr [[ADDR_31:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: `-ImplicitCastExpr [[ADDR_32:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CHECK-NEXT: `-DeclRefExpr [[ADDR_33:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_17]] 'also_before' 'int ({{.*}})' diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_7.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_7.c new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_7.c @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s +// expected-no-diagnostics + +int OK_1(void); + +#pragma omp begin declare variant match(implementation={vendor(intel)}) +int OK_1(void) { + return 1; +} +int OK_2(void) { + return 1; +} +int not_OK(void) { + return 1; +} +int OK_3(void) { + return 1; +} +#pragma omp end declare variant + +int OK_3(void); + +int test() { + // Should cause an error due to not_OK() + return OK_1() + not_OK() + OK_3(); +} + +// Make sure: +// - we see a single error for `not_OK` +// - we do not see errors for OK_{1,2,3} +// FIXME: We actually do not see there error here. +// This case is unlikely to happen in practise and hard to diagnose during SEMA. +// We will issue an error during code generation instead. This is similar to the +// diagnosis in other multi-versioning schemes. + +// CHECK: |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, col:14> col:5 used OK_1 'int ({{.*}})' +// CHECK-NEXT: |-NamespaceDecl [[ADDR_1:0x[a-z0-9]*]] line:7:72 __omp_declare_variant_scope +// CHECK-NEXT: | |-FunctionDecl [[ADDR_2:0x[a-z0-9]*]] line:8:5 used __OK_1 'int ({{.*}})' +// CHECK-NEXT: | | |-CompoundStmt [[ADDR_3:0x[a-z0-9]*]] +// CHECK-NEXT: | | | `-ReturnStmt [[ADDR_4:0x[a-z0-9]*]] +// CHECK-NEXT: | | | `-IntegerLiteral [[ADDR_5:0x[a-z0-9]*]] 'int' 1 +// CHECK-NEXT: | | `-OMPMultiVersionDeclareVariantAttr [[ADDR_6:0x[a-z0-9]*]] implementation={vendor(intel)} +// CHECK-NEXT: | |-FunctionDecl [[ADDR_7:0x[a-z0-9]*]] line:11:5 __OK_2 'int ({{.*}})' +// CHECK-NEXT: | | |-CompoundStmt [[ADDR_8:0x[a-z0-9]*]] +// CHECK-NEXT: | | | `-ReturnStmt [[ADDR_9:0x[a-z0-9]*]] +// CHECK-NEXT: | | | `-IntegerLiteral [[ADDR_10:0x[a-z0-9]*]] 'int' 1 +// CHECK-NEXT: | | `-OMPMultiVersionDeclareVariantAttr [[ADDR_11:0x[a-z0-9]*]] implementation={vendor(intel)} +// CHECK-NEXT: | |-FunctionDecl [[ADDR_12:0x[a-z0-9]*]] line:14:5 used __not_OK 'int ({{.*}})' +// CHECK-NEXT: | | |-CompoundStmt [[ADDR_13:0x[a-z0-9]*]] +// CHECK-NEXT: | | | `-ReturnStmt [[ADDR_14:0x[a-z0-9]*]] +// CHECK-NEXT: | | | `-IntegerLiteral [[ADDR_15:0x[a-z0-9]*]] 'int' 1 +// CHECK-NEXT: | | `-OMPMultiVersionDeclareVariantAttr [[ADDR_16:0x[a-z0-9]*]] implementation={vendor(intel)} +// CHECK-NEXT: | `-FunctionDecl [[ADDR_17:0x[a-z0-9]*]] line:17:5 used __OK_3 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_18:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_19:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_20:0x[a-z0-9]*]] 'int' 1 +// CHECK-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_21:0x[a-z0-9]*]] implementation={vendor(intel)} +// CHECK-NEXT: |-FunctionDecl [[ADDR_22:0x[a-z0-9]*]] prev [[ADDR_0]] line:8:5 implicit used OK_1 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_23:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_24:0x[a-z0-9]*]] line:11:5 implicit OK_2 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_25:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_26:0x[a-z0-9]*]] line:14:5 implicit used not_OK 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_27:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_28:0x[a-z0-9]*]] line:17:5 implicit used OK_3 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_29:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_30:0x[a-z0-9]*]] prev [[ADDR_28]] col:5 used OK_3 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_31:0x[a-z0-9]*]] Inherited Implicit +// CHECK-NEXT: `-FunctionDecl [[ADDR_32:0x[a-z0-9]*]] line:24:5 test 'int ({{.*}})' +// CHECK-NEXT: `-CompoundStmt [[ADDR_33:0x[a-z0-9]*]] +// CHECK-NEXT: `-ReturnStmt [[ADDR_34:0x[a-z0-9]*]] +// CHECK-NEXT: `-BinaryOperator [[ADDR_35:0x[a-z0-9]*]] 'int' '+' +// CHECK-NEXT: |-BinaryOperator [[ADDR_36:0x[a-z0-9]*]] 'int' '+' +// CHECK-NEXT: | |-CallExpr [[ADDR_37:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | | `-ImplicitCastExpr [[ADDR_38:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CHECK-NEXT: | | `-DeclRefExpr [[ADDR_39:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_22]] 'OK_1' 'int ({{.*}})' +// CHECK-NEXT: | `-CallExpr [[ADDR_40:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | `-ImplicitCastExpr [[ADDR_41:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CHECK-NEXT: | `-DeclRefExpr [[ADDR_42:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_26]] 'not_OK' 'int ({{.*}})' +// CHECK-NEXT: `-CallExpr [[ADDR_43:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: `-ImplicitCastExpr [[ADDR_44:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CHECK-NEXT: `-DeclRefExpr [[ADDR_45:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_30]] 'OK_3' 'int ({{.*}})' diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_8.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_8.c new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_8.c @@ -0,0 +1,76 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s +// expected-no-diagnostics + +#pragma omp begin declare variant match(device={kind(cpu)}) +int also_before(void) { + return 1; +} +#pragma omp end declare variant + +#pragma omp begin declare variant match(implementation={vendor(score(0):llvm)}) +int also_after(void) { + return 0; +} +#pragma omp end declare variant +#pragma omp begin declare variant match(implementation={vendor(score(100):llvm)}) +int also_before(void) { + return 0; +} +#pragma omp end declare variant + +int also_after(void) { + return 2; +} + +int test() { + // Should return 0. + return also_after() + also_before(); +} + +// Make sure: +// - we do see the ast nodes for the cpu kind +// - we do see the ast nodes for the llvm vendor +// - we pick the right callees + +// CHECK: |-NamespaceDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:9:1> line:5:60 __omp_declare_variant_scope +// CHECK-NEXT: | `-FunctionDecl [[ADDR_1:0x[a-z0-9]*]] line:6:5 __also_before 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_2:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_3:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_4:0x[a-z0-9]*]] 'int' 1 +// CHECK-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_5:0x[a-z0-9]*]] device={kind(cpu)} +// CHECK-NEXT: |-FunctionDecl [[ADDR_6:0x[a-z0-9]*]] line:6:5 implicit used also_before 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_7:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-NamespaceDecl [[ADDR_8:0x[a-z0-9]*]] prev [[ADDR_0]] line:11:80 __omp_declare_variant_scope +// CHECK-NEXT: | |-original Namespace [[ADDR_0]] '__omp_declare_variant_scope' +// CHECK-NEXT: | `-FunctionDecl [[ADDR_9:0x[a-z0-9]*]] line:12:5 used __also_after 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_10:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_11:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_12:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_13:0x[a-z0-9]*]] implementation={vendor(score(0): llvm)} +// CHECK-NEXT: |-FunctionDecl [[ADDR_14:0x[a-z0-9]*]] line:12:5 implicit used also_after 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_15:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-NamespaceDecl [[ADDR_16:0x[a-z0-9]*]] prev [[ADDR_8]] line:16:82 __omp_declare_variant_scope +// CHECK-NEXT: | |-original Namespace [[ADDR_0]] '__omp_declare_variant_scope' +// CHECK-NEXT: | `-FunctionDecl [[ADDR_17:0x[a-z0-9]*]] line:17:5 used __also_before 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_18:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_19:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_20:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_21:0x[a-z0-9]*]] implementation={vendor(score(100): llvm)} +// CHECK-NEXT: |-FunctionDecl [[ADDR_22:0x[a-z0-9]*]] prev [[ADDR_6]] line:17:5 implicit used also_before 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_23:0x[a-z0-9]*]] Inherited Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_24:0x[a-z0-9]*]] prev [[ADDR_14]] line:22:5 used also_after 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_25:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_26:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_27:0x[a-z0-9]*]] 'int' 2 +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_28:0x[a-z0-9]*]] Inherited Implicit +// CHECK-NEXT: `-FunctionDecl [[ADDR_29:0x[a-z0-9]*]] line:26:5 test 'int ({{.*}})' +// CHECK-NEXT: `-CompoundStmt [[ADDR_30:0x[a-z0-9]*]] +// CHECK-NEXT: `-ReturnStmt [[ADDR_31:0x[a-z0-9]*]] +// CHECK-NEXT: `-BinaryOperator [[ADDR_32:0x[a-z0-9]*]] 'int' '+' +// CHECK-NEXT: |-CallExpr [[ADDR_33:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | `-ImplicitCastExpr [[ADDR_34:0x[a-z0-9]*]] > 'int (*)({{.*}})' +// CHECK-NEXT: | `-DeclRefExpr [[ADDR_35:0x[a-z0-9]*]] > 'int ({{.*}})' {{.*}}Function [[ADDR_9]] '__also_after' 'int ({{.*}})' +// CHECK-NEXT: `-CallExpr [[ADDR_36:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: `-ImplicitCastExpr [[ADDR_37:0x[a-z0-9]*]] > 'int (*)({{.*}})' +// CHECK-NEXT: `-DeclRefExpr [[ADDR_38:0x[a-z0-9]*]] > 'int ({{.*}})' {{.*}}Function [[ADDR_17]] '__also_before' 'int ({{.*}})' diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_9.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_9.c new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_9.c @@ -0,0 +1,184 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s | FileCheck %s --check-prefix=C +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s --check-prefix=CXX +// expected-no-diagnostics + +int also_before(void) { + return 0; +} + +#pragma omp begin declare variant match(implementation={vendor(llvm)}) +int also_after(void) { + return 1; +} +int also_before(void) { + return 2; +} +#pragma omp end declare variant + +int also_after(void) { + return 0; +} + +void foo(); +typedef int(*fd)(void); +int main() { + // Should return 0. + fd fns[2]; + fns[0] = &also_before; + fns[1] = also_after; + return (foo(), also_after)() + + (fns[0])() + + (1[fns])(); +} + +// Make sure: +// - we see the specialization in the AST +// - we pick the right callees + +// CXX: |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})' +// CXX-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] +// CXX-NEXT: | `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] +// CXX-NEXT: | `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] 'int' 0 +// CXX-NEXT: |-NamespaceDecl [[ADDR_4:0x[a-z0-9]*]] line:9:71 __omp_declare_variant_scope +// CXX-NEXT: | |-FunctionDecl [[ADDR_5:0x[a-z0-9]*]] line:10:5 __also_after 'int ({{.*}})' +// CXX-NEXT: | | |-CompoundStmt [[ADDR_6:0x[a-z0-9]*]] +// CXX-NEXT: | | | `-ReturnStmt [[ADDR_7:0x[a-z0-9]*]] +// CXX-NEXT: | | | `-IntegerLiteral [[ADDR_8:0x[a-z0-9]*]] 'int' 1 +// CXX-NEXT: | | `-OMPMultiVersionDeclareVariantAttr [[ADDR_9:0x[a-z0-9]*]] implementation={vendor(llvm)} +// CXX-NEXT: | `-FunctionDecl [[ADDR_10:0x[a-z0-9]*]] line:13:5 __also_before 'int ({{.*}})' +// CXX-NEXT: | |-CompoundStmt [[ADDR_11:0x[a-z0-9]*]] +// CXX-NEXT: | | `-ReturnStmt [[ADDR_12:0x[a-z0-9]*]] +// CXX-NEXT: | | `-IntegerLiteral [[ADDR_13:0x[a-z0-9]*]] 'int' 2 +// CXX-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_14:0x[a-z0-9]*]] implementation={vendor(llvm)} +// CXX-NEXT: |-FunctionDecl [[ADDR_15:0x[a-z0-9]*]] line:10:5 implicit used also_after 'int ({{.*}})' +// CXX-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_16:0x[a-z0-9]*]] Implicit +// CXX-NEXT: |-FunctionDecl [[ADDR_17:0x[a-z0-9]*]] prev [[ADDR_0]] line:13:5 implicit used also_before 'int ({{.*}})' +// CXX-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_18:0x[a-z0-9]*]] Implicit +// CXX-NEXT: |-FunctionDecl [[ADDR_19:0x[a-z0-9]*]] prev [[ADDR_15]] line:18:5 used also_after 'int ({{.*}})' +// CXX-NEXT: | |-CompoundStmt [[ADDR_20:0x[a-z0-9]*]] +// CXX-NEXT: | | `-ReturnStmt [[ADDR_21:0x[a-z0-9]*]] +// CXX-NEXT: | | `-IntegerLiteral [[ADDR_22:0x[a-z0-9]*]] 'int' 0 +// CXX-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_23:0x[a-z0-9]*]] Inherited Implicit +// CXX-NEXT: |-FunctionDecl [[ADDR_24:0x[a-z0-9]*]] col:6 used foo 'void ({{.*}})' +// CXX-NEXT: |-TypedefDecl [[ADDR_25:0x[a-z0-9]*]] col:14 referenced fd 'int (*)({{.*}})' +// CXX-NEXT: | `-PointerType [[ADDR_26:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CXX-NEXT: | `-ParenType [[ADDR_27:0x[a-z0-9]*]] 'int ({{.*}})' sugar +// CXX-NEXT: | `-FunctionProtoType [[ADDR_28:0x[a-z0-9]*]] 'int ({{.*}})' cdecl +// CXX-NEXT: | `-BuiltinType [[ADDR_29:0x[a-z0-9]*]] 'int' +// CXX-NEXT: `-FunctionDecl [[ADDR_30:0x[a-z0-9]*]] line:24:5 main 'int ({{.*}})' +// CXX-NEXT: `-CompoundStmt [[ADDR_31:0x[a-z0-9]*]] +// CXX-NEXT: |-DeclStmt [[ADDR_32:0x[a-z0-9]*]] +// CXX-NEXT: | `-VarDecl [[ADDR_33:0x[a-z0-9]*]] col:6 used fns 'fd [2]' +// CXX-NEXT: |-BinaryOperator [[ADDR_34:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' {{.*}}'=' +// CXX-NEXT: | |-ArraySubscriptExpr [[ADDR_35:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' lvalue +// CXX-NEXT: | | |-ImplicitCastExpr [[ADDR_36:0x[a-z0-9]*]] 'fd *' +// CXX-NEXT: | | | `-DeclRefExpr [[ADDR_37:0x[a-z0-9]*]] 'fd [2]' {{.*}}Var [[ADDR_33]] 'fns' 'fd [2]' +// CXX-NEXT: | | `-IntegerLiteral [[ADDR_38:0x[a-z0-9]*]] 'int' 0 +// CXX-NEXT: | `-UnaryOperator [[ADDR_39:0x[a-z0-9]*]] 'int (*)({{.*}})' prefix '&' cannot overflow +// CXX-NEXT: | `-DeclRefExpr [[ADDR_40:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_17]] 'also_before' 'int ({{.*}})' +// CXX-NEXT: |-BinaryOperator [[ADDR_41:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' {{.*}}'=' +// CXX-NEXT: | |-ArraySubscriptExpr [[ADDR_42:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' lvalue +// CXX-NEXT: | | |-ImplicitCastExpr [[ADDR_43:0x[a-z0-9]*]] 'fd *' +// CXX-NEXT: | | | `-DeclRefExpr [[ADDR_44:0x[a-z0-9]*]] 'fd [2]' {{.*}}Var [[ADDR_33]] 'fns' 'fd [2]' +// CXX-NEXT: | | `-IntegerLiteral [[ADDR_45:0x[a-z0-9]*]] 'int' 1 +// CXX-NEXT: | `-ImplicitCastExpr [[ADDR_46:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CXX-NEXT: | `-DeclRefExpr [[ADDR_47:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_19]] 'also_after' 'int ({{.*}})' +// CXX-NEXT: `-ReturnStmt [[ADDR_48:0x[a-z0-9]*]] +// CXX-NEXT: `-BinaryOperator [[ADDR_49:0x[a-z0-9]*]] 'int' '+' +// CXX-NEXT: |-BinaryOperator [[ADDR_50:0x[a-z0-9]*]] 'int' '+' +// CXX-NEXT: | |-CallExpr [[ADDR_51:0x[a-z0-9]*]] 'int' +// CXX-NEXT: | | `-ImplicitCastExpr [[ADDR_52:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CXX-NEXT: | | `-ParenExpr [[ADDR_53:0x[a-z0-9]*]] 'int ({{.*}})' lvalue +// CXX-NEXT: | | `-BinaryOperator [[ADDR_54:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}',' +// CXX-NEXT: | | |-CallExpr [[ADDR_55:0x[a-z0-9]*]] 'void' +// CXX-NEXT: | | | `-ImplicitCastExpr [[ADDR_56:0x[a-z0-9]*]] 'void (*)({{.*}})' +// CXX-NEXT: | | | `-DeclRefExpr [[ADDR_57:0x[a-z0-9]*]] 'void ({{.*}})' {{.*}}Function [[ADDR_24]] 'foo' 'void ({{.*}})' +// CXX-NEXT: | | `-DeclRefExpr [[ADDR_58:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_19]] 'also_after' 'int ({{.*}})' +// CXX-NEXT: | `-CallExpr [[ADDR_59:0x[a-z0-9]*]] 'int' +// CXX-NEXT: | `-ImplicitCastExpr [[ADDR_60:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' +// CXX-NEXT: | `-ParenExpr [[ADDR_61:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' lvalue +// CXX-NEXT: | `-ArraySubscriptExpr [[ADDR_62:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' lvalue +// CXX-NEXT: | |-ImplicitCastExpr [[ADDR_63:0x[a-z0-9]*]] 'fd *' +// CXX-NEXT: | | `-DeclRefExpr [[ADDR_64:0x[a-z0-9]*]] 'fd [2]' {{.*}}Var [[ADDR_33]] 'fns' 'fd [2]' +// CXX-NEXT: | `-IntegerLiteral [[ADDR_65:0x[a-z0-9]*]] 'int' 0 +// CXX-NEXT: `-CallExpr [[ADDR_66:0x[a-z0-9]*]] 'int' +// CXX-NEXT: `-ImplicitCastExpr [[ADDR_67:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' +// CXX-NEXT: `-ParenExpr [[ADDR_68:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' lvalue +// CXX-NEXT: `-ArraySubscriptExpr [[ADDR_69:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' lvalue +// CXX-NEXT: |-IntegerLiteral [[ADDR_70:0x[a-z0-9]*]] 'int' 1 +// CXX-NEXT: `-ImplicitCastExpr [[ADDR_71:0x[a-z0-9]*]] 'fd *' +// CXX-NEXT: `-DeclRefExpr [[ADDR_72:0x[a-z0-9]*]] 'fd [2]' {{.*}}Var [[ADDR_33]] 'fns' 'fd [2]' + +// C: |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})' +// C-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] +// C-NEXT: | `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] +// C-NEXT: | `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] 'int' 0 +// C-NEXT: |-NamespaceDecl [[ADDR_4:0x[a-z0-9]*]] line:9:71 __omp_declare_variant_scope +// C-NEXT: | |-FunctionDecl [[ADDR_5:0x[a-z0-9]*]] line:10:5 __also_after 'int ({{.*}})' +// C-NEXT: | | |-CompoundStmt [[ADDR_6:0x[a-z0-9]*]] +// C-NEXT: | | | `-ReturnStmt [[ADDR_7:0x[a-z0-9]*]] +// C-NEXT: | | | `-IntegerLiteral [[ADDR_8:0x[a-z0-9]*]] 'int' 1 +// C-NEXT: | | `-OMPMultiVersionDeclareVariantAttr [[ADDR_9:0x[a-z0-9]*]] implementation={vendor(llvm)} +// C-NEXT: | `-FunctionDecl [[ADDR_10:0x[a-z0-9]*]] line:13:5 __also_before 'int ({{.*}})' +// C-NEXT: | |-CompoundStmt [[ADDR_11:0x[a-z0-9]*]] +// C-NEXT: | | `-ReturnStmt [[ADDR_12:0x[a-z0-9]*]] +// C-NEXT: | | `-IntegerLiteral [[ADDR_13:0x[a-z0-9]*]] 'int' 2 +// C-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_14:0x[a-z0-9]*]] implementation={vendor(llvm)} +// C-NEXT: |-FunctionDecl [[ADDR_15:0x[a-z0-9]*]] line:10:5 implicit used also_after 'int ({{.*}})' +// C-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_16:0x[a-z0-9]*]] Implicit +// C-NEXT: |-FunctionDecl [[ADDR_17:0x[a-z0-9]*]] prev [[ADDR_0]] line:13:5 implicit used also_before 'int ({{.*}})' +// C-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_18:0x[a-z0-9]*]] Implicit +// C-NEXT: |-FunctionDecl [[ADDR_19:0x[a-z0-9]*]] prev [[ADDR_15]] line:18:5 used also_after 'int ({{.*}})' +// C-NEXT: | |-CompoundStmt [[ADDR_20:0x[a-z0-9]*]] +// C-NEXT: | | `-ReturnStmt [[ADDR_21:0x[a-z0-9]*]] +// C-NEXT: | | `-IntegerLiteral [[ADDR_22:0x[a-z0-9]*]] 'int' 0 +// C-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_23:0x[a-z0-9]*]] Inherited Implicit +// C-NEXT: |-FunctionDecl [[ADDR_24:0x[a-z0-9]*]] col:6 used foo 'void ({{.*}})' +// C-NEXT: |-TypedefDecl [[ADDR_25:0x[a-z0-9]*]] col:14 referenced fd 'int (*)({{.*}})' +// C-NEXT: | `-PointerType [[ADDR_26:0x[a-z0-9]*]] 'int (*)({{.*}})' +// C-NEXT: | `-ParenType [[ADDR_27:0x[a-z0-9]*]] 'int ({{.*}})' sugar +// C-NEXT: | `-FunctionProtoType [[ADDR_28:0x[a-z0-9]*]] 'int ({{.*}})' cdecl +// C-NEXT: | `-BuiltinType [[ADDR_29:0x[a-z0-9]*]] 'int' +// C-NEXT: `-FunctionDecl [[ADDR_30:0x[a-z0-9]*]] line:24:5 main 'int ({{.*}})' +// C-NEXT: `-CompoundStmt [[ADDR_31:0x[a-z0-9]*]] +// C-NEXT: |-DeclStmt [[ADDR_32:0x[a-z0-9]*]] +// C-NEXT: | `-VarDecl [[ADDR_33:0x[a-z0-9]*]] col:6 used fns 'fd [2]' +// C-NEXT: |-BinaryOperator [[ADDR_34:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' '=' +// C-NEXT: | |-ArraySubscriptExpr [[ADDR_35:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' lvalue +// C-NEXT: | | |-ImplicitCastExpr [[ADDR_36:0x[a-z0-9]*]] 'fd *' +// C-NEXT: | | | `-DeclRefExpr [[ADDR_37:0x[a-z0-9]*]] 'fd [2]' {{.*}}Var [[ADDR_33]] 'fns' 'fd [2]' +// C-NEXT: | | `-IntegerLiteral [[ADDR_38:0x[a-z0-9]*]] 'int' 0 +// C-NEXT: | `-UnaryOperator [[ADDR_39:0x[a-z0-9]*]] 'int (*)({{.*}})' prefix '&' cannot overflow +// C-NEXT: | `-DeclRefExpr [[ADDR_40:0x[a-z0-9]*]] 'int ({{.*}})' Function [[ADDR_17]] 'also_before' 'int ({{.*}})' +// C-NEXT: |-BinaryOperator [[ADDR_41:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' '=' +// C-NEXT: | |-ArraySubscriptExpr [[ADDR_42:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' lvalue +// C-NEXT: | | |-ImplicitCastExpr [[ADDR_43:0x[a-z0-9]*]] 'fd *' +// C-NEXT: | | | `-DeclRefExpr [[ADDR_44:0x[a-z0-9]*]] 'fd [2]' {{.*}}Var [[ADDR_33]] 'fns' 'fd [2]' +// C-NEXT: | | `-IntegerLiteral [[ADDR_45:0x[a-z0-9]*]] 'int' 1 +// C-NEXT: | `-ImplicitCastExpr [[ADDR_46:0x[a-z0-9]*]] 'int (*)({{.*}})' +// C-NEXT: | `-DeclRefExpr [[ADDR_47:0x[a-z0-9]*]] 'int ({{.*}})' Function [[ADDR_19]] 'also_after' 'int ({{.*}})' +// C-NEXT: `-ReturnStmt [[ADDR_48:0x[a-z0-9]*]] +// C-NEXT: `-BinaryOperator [[ADDR_49:0x[a-z0-9]*]] 'int' '+' +// C-NEXT: |-BinaryOperator [[ADDR_50:0x[a-z0-9]*]] 'int' '+' +// C-NEXT: | |-CallExpr [[ADDR_51:0x[a-z0-9]*]] 'int' +// C-NEXT: | | `-ParenExpr [[ADDR_52:0x[a-z0-9]*]] 'int (*)({{.*}})' +// C-NEXT: | | `-BinaryOperator [[ADDR_53:0x[a-z0-9]*]] 'int (*)({{.*}})' ',' +// C-NEXT: | | |-CallExpr [[ADDR_54:0x[a-z0-9]*]] 'void' +// C-NEXT: | | | `-ImplicitCastExpr [[ADDR_55:0x[a-z0-9]*]] 'void (*)({{.*}})' +// C-NEXT: | | | `-DeclRefExpr [[ADDR_56:0x[a-z0-9]*]] 'void ({{.*}})' Function [[ADDR_24]] 'foo' 'void ({{.*}})' +// C-NEXT: | | `-ImplicitCastExpr [[ADDR_57:0x[a-z0-9]*]] 'int (*)({{.*}})' +// C-NEXT: | | `-DeclRefExpr [[ADDR_58:0x[a-z0-9]*]] 'int ({{.*}})' Function [[ADDR_19]] 'also_after' 'int ({{.*}})' +// C-NEXT: | `-CallExpr [[ADDR_59:0x[a-z0-9]*]] 'int' +// C-NEXT: | `-ImplicitCastExpr [[ADDR_60:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' +// C-NEXT: | `-ParenExpr [[ADDR_61:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' lvalue +// C-NEXT: | `-ArraySubscriptExpr [[ADDR_62:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' lvalue +// C-NEXT: | |-ImplicitCastExpr [[ADDR_63:0x[a-z0-9]*]] 'fd *' +// C-NEXT: | | `-DeclRefExpr [[ADDR_64:0x[a-z0-9]*]] 'fd [2]' {{.*}}Var [[ADDR_33]] 'fns' 'fd [2]' +// C-NEXT: | `-IntegerLiteral [[ADDR_65:0x[a-z0-9]*]] 'int' 0 +// C-NEXT: `-CallExpr [[ADDR_66:0x[a-z0-9]*]] 'int' +// C-NEXT: `-ImplicitCastExpr [[ADDR_67:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' +// C-NEXT: `-ParenExpr [[ADDR_68:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' lvalue +// C-NEXT: `-ArraySubscriptExpr [[ADDR_69:0x[a-z0-9]*]] 'fd':'int (*)({{.*}})' lvalue +// C-NEXT: |-IntegerLiteral [[ADDR_70:0x[a-z0-9]*]] 'int' 1 +// C-NEXT: `-ImplicitCastExpr [[ADDR_71:0x[a-z0-9]*]] 'fd *' +// C-NEXT: `-DeclRefExpr [[ADDR_72:0x[a-z0-9]*]] 'fd [2]' {{.*}}Var [[ADDR_33]] 'fns' 'fd [2]' diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_addr_1.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_addr_1.c new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_addr_1.c @@ -0,0 +1,93 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s +// expected-no-diagnostics + +int also_before(void) { + return 0; +} + +#pragma omp begin declare variant match(implementation={vendor(llvm)}) +int also_after(void) { + return 1; +} +int also_before(void) { + return 2; +} +#pragma omp end declare variant + +int also_after(void) { + return 0; +} + +int test(int (*fd)(void)) { + return fd(); +} +int main() { + // Should return 0. + return test(also_after) + + test(also_before) + + test(&also_after) + + test(&also_before); +} + +// Make sure: +// - we see the specialization in the AST +// - we pick the right callees + +// CHECK: |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})' +// CHECK-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] +// CHECK-NEXT: | `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] +// CHECK-NEXT: | `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: |-NamespaceDecl [[ADDR_4:0x[a-z0-9]*]] line:9:71 __omp_declare_variant_scope +// CHECK-NEXT: | |-FunctionDecl [[ADDR_5:0x[a-z0-9]*]] line:10:5 __also_after 'int ({{.*}})' +// CHECK-NEXT: | | |-CompoundStmt [[ADDR_6:0x[a-z0-9]*]] +// CHECK-NEXT: | | | `-ReturnStmt [[ADDR_7:0x[a-z0-9]*]] +// CHECK-NEXT: | | | `-IntegerLiteral [[ADDR_8:0x[a-z0-9]*]] 'int' 1 +// CHECK-NEXT: | | `-OMPMultiVersionDeclareVariantAttr [[ADDR_9:0x[a-z0-9]*]] implementation={vendor(llvm)} +// CHECK-NEXT: | `-FunctionDecl [[ADDR_10:0x[a-z0-9]*]] line:13:5 __also_before 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_11:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_12:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_13:0x[a-z0-9]*]] 'int' 2 +// CHECK-NEXT: | `-OMPMultiVersionDeclareVariantAttr [[ADDR_14:0x[a-z0-9]*]] implementation={vendor(llvm)} +// CHECK-NEXT: |-FunctionDecl [[ADDR_15:0x[a-z0-9]*]] line:10:5 implicit used also_after 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_16:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_17:0x[a-z0-9]*]] prev [[ADDR_0]] line:13:5 implicit used also_before 'int ({{.*}})' +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_18:0x[a-z0-9]*]] Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_19:0x[a-z0-9]*]] prev [[ADDR_15]] line:18:5 used also_after 'int ({{.*}})' +// CHECK-NEXT: | |-CompoundStmt [[ADDR_20:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-ReturnStmt [[ADDR_21:0x[a-z0-9]*]] +// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_22:0x[a-z0-9]*]] 'int' 0 +// CHECK-NEXT: | `-OMPMultiVersionDeclareBaseAttr [[ADDR_23:0x[a-z0-9]*]] Inherited Implicit +// CHECK-NEXT: |-FunctionDecl [[ADDR_24:0x[a-z0-9]*]] line:22:5 used test 'int (int (*)({{.*}}))' +// CHECK-NEXT: | |-ParmVarDecl [[ADDR_25:0x[a-z0-9]*]] col:16 used fd 'int (*)({{.*}})' +// CHECK-NEXT: | `-CompoundStmt [[ADDR_26:0x[a-z0-9]*]] +// CHECK-NEXT: | `-ReturnStmt [[ADDR_27:0x[a-z0-9]*]] +// CHECK-NEXT: | `-CallExpr [[ADDR_28:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | `-ImplicitCastExpr [[ADDR_29:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CHECK-NEXT: | `-DeclRefExpr [[ADDR_30:0x[a-z0-9]*]] 'int (*)({{.*}})' {{.*}}ParmVar [[ADDR_25]] 'fd' 'int (*)({{.*}})' +// CHECK-NEXT: `-FunctionDecl [[ADDR_31:0x[a-z0-9]*]] line:25:5 main 'int ({{.*}})' +// CHECK-NEXT: `-CompoundStmt [[ADDR_32:0x[a-z0-9]*]] +// CHECK-NEXT: `-ReturnStmt [[ADDR_33:0x[a-z0-9]*]] +// CHECK-NEXT: `-BinaryOperator [[ADDR_34:0x[a-z0-9]*]] 'int' '+' +// CHECK-NEXT: |-BinaryOperator [[ADDR_35:0x[a-z0-9]*]] 'int' '+' +// CHECK-NEXT: | |-BinaryOperator [[ADDR_36:0x[a-z0-9]*]] 'int' '+' +// CHECK-NEXT: | | |-CallExpr [[ADDR_37:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | | | |-ImplicitCastExpr [[ADDR_38:0x[a-z0-9]*]] 'int (*)(int (*)({{.*}}))' +// CHECK-NEXT: | | | | `-DeclRefExpr [[ADDR_39:0x[a-z0-9]*]] 'int (int (*)({{.*}}))' {{.*}}Function [[ADDR_24]] 'test' 'int (int (*)({{.*}}))' +// CHECK-NEXT: | | | `-ImplicitCastExpr [[ADDR_40:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CHECK-NEXT: | | | `-DeclRefExpr [[ADDR_41:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_19]] 'also_after' 'int ({{.*}})' +// CHECK-NEXT: | | `-CallExpr [[ADDR_42:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | | |-ImplicitCastExpr [[ADDR_43:0x[a-z0-9]*]] 'int (*)(int (*)({{.*}}))' +// CHECK-NEXT: | | | `-DeclRefExpr [[ADDR_44:0x[a-z0-9]*]] 'int (int (*)({{.*}}))' {{.*}}Function [[ADDR_24]] 'test' 'int (int (*)({{.*}}))' +// CHECK-NEXT: | | `-ImplicitCastExpr [[ADDR_45:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CHECK-NEXT: | | `-DeclRefExpr [[ADDR_46:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_17]] 'also_before' 'int ({{.*}})' +// CHECK-NEXT: | `-CallExpr [[ADDR_47:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: | |-ImplicitCastExpr [[ADDR_48:0x[a-z0-9]*]] 'int (*)(int (*)({{.*}}))' +// CHECK-NEXT: | | `-DeclRefExpr [[ADDR_49:0x[a-z0-9]*]] 'int (int (*)({{.*}}))' {{.*}}Function [[ADDR_24]] 'test' 'int (int (*)({{.*}}))' +// CHECK-NEXT: | `-UnaryOperator [[ADDR_50:0x[a-z0-9]*]] 'int (*)({{.*}})' prefix '&' cannot overflow +// CHECK-NEXT: | `-DeclRefExpr [[ADDR_51:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_19]] 'also_after' 'int ({{.*}})' +// CHECK-NEXT: `-CallExpr [[ADDR_52:0x[a-z0-9]*]] 'int' +// CHECK-NEXT: |-ImplicitCastExpr [[ADDR_53:0x[a-z0-9]*]] 'int (*)(int (*)({{.*}}))' +// CHECK-NEXT: | `-DeclRefExpr [[ADDR_54:0x[a-z0-9]*]] 'int (int (*)({{.*}}))' {{.*}}Function [[ADDR_24]] 'test' 'int (int (*)({{.*}}))' +// CHECK-NEXT: `-UnaryOperator [[ADDR_55:0x[a-z0-9]*]] 'int (*)({{.*}})' prefix '&' cannot overflow +// CHECK-NEXT: `-DeclRefExpr [[ADDR_56:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_17]] 'also_before' 'int ({{.*}})' diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_decl_1.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_decl_1.c new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_decl_1.c @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s | FileCheck %s --check-prefix=C +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s --check-prefix=CXX +// expected-no-diagnostics +// FIXME: We have to improve the warnings here as nothing is impacted by the declare variant. +int also_before(void) { + return 0; +} + +#pragma omp begin declare variant match(device={kind(cpu)}) +int also_before(void); +#pragma omp end declare variant +#pragma omp begin declare variant match(implementation={vendor(score(100):llvm)}) +int also_after(void); +#pragma omp end declare variant +#pragma omp begin declare variant match(implementation={vendor(score(0):llvm)}) +int also_before(void); +#pragma omp end declare variant + +int also_after(void) { + return 0; +} + +int test() { + // Should return 0. + return also_after() + also_before(); +} + +// Make sure: +// - we do see the ast nodes for the cpu kind +// - we do see the ast nodes for the llvm vendor +// - we pick the right callees + +// CXX: |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})' +// CXX-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] +// CXX-NEXT: | `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] +// CXX-NEXT: | `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] 'int' 0 +// CXX-NEXT: |-NamespaceDecl [[ADDR_4:0x[a-z0-9]*]] line:9:60 __omp_declare_variant_scope +// CXX-NEXT: | `-FunctionDecl [[ADDR_5:0x[a-z0-9]*]] col:5 also_before 'int ({{.*}})' +// CXX-NEXT: |-NamespaceDecl [[ADDR_6:0x[a-z0-9]*]] prev [[ADDR_4]] line:12:82 __omp_declare_variant_scope +// CXX-NEXT: | |-original Namespace [[ADDR_4]] '__omp_declare_variant_scope' +// CXX-NEXT: | `-FunctionDecl [[ADDR_7:0x[a-z0-9]*]] col:5 also_after 'int ({{.*}})' +// CXX-NEXT: |-NamespaceDecl [[ADDR_8:0x[a-z0-9]*]] prev [[ADDR_6]] line:15:80 __omp_declare_variant_scope +// CXX-NEXT: | |-original Namespace [[ADDR_4]] '__omp_declare_variant_scope' +// CXX-NEXT: | `-FunctionDecl [[ADDR_9:0x[a-z0-9]*]] prev [[ADDR_5]] col:5 also_before 'int ({{.*}})' +// CXX-NEXT: |-FunctionDecl [[ADDR_10:0x[a-z0-9]*]] line:19:5 used also_after 'int ({{.*}})' +// CXX-NEXT: | `-CompoundStmt [[ADDR_11:0x[a-z0-9]*]] +// CXX-NEXT: | `-ReturnStmt [[ADDR_12:0x[a-z0-9]*]] +// CXX-NEXT: | `-IntegerLiteral [[ADDR_13:0x[a-z0-9]*]] 'int' 0 +// CXX-NEXT: `-FunctionDecl [[ADDR_14:0x[a-z0-9]*]] line:23:5 test 'int ({{.*}})' +// CXX-NEXT: `-CompoundStmt [[ADDR_15:0x[a-z0-9]*]] +// CXX-NEXT: `-ReturnStmt [[ADDR_16:0x[a-z0-9]*]] +// CXX-NEXT: `-BinaryOperator [[ADDR_17:0x[a-z0-9]*]] 'int' '+' +// CXX-NEXT: |-CallExpr [[ADDR_18:0x[a-z0-9]*]] 'int' +// CXX-NEXT: | `-ImplicitCastExpr [[ADDR_19:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CXX-NEXT: | `-DeclRefExpr [[ADDR_20:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_10]] 'also_after' 'int ({{.*}})' +// CXX-NEXT: `-CallExpr [[ADDR_21:0x[a-z0-9]*]] 'int' +// CXX-NEXT: `-ImplicitCastExpr [[ADDR_22:0x[a-z0-9]*]] 'int (*)({{.*}})' +// CXX-NEXT: `-DeclRefExpr [[ADDR_23:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_0]] 'also_before' 'int ({{.*}})' + +// C: |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})' +// C-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] +// C-NEXT: | `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] +// C-NEXT: | `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] 'int' 0 +// C-NEXT: |-NamespaceDecl [[ADDR_4:0x[a-z0-9]*]] line:9:60 __omp_declare_variant_scope +// C-NEXT: | `-FunctionDecl [[ADDR_5:0x[a-z0-9]*]] col:5 also_before 'int ({{.*}})' +// C-NEXT: |-NamespaceDecl [[ADDR_6:0x[a-z0-9]*]] prev [[ADDR_4]] line:12:82 __omp_declare_variant_scope +// C-NEXT: | |-original Namespace [[ADDR_4]] '__omp_declare_variant_scope' +// C-NEXT: | `-FunctionDecl [[ADDR_7:0x[a-z0-9]*]] col:5 used also_after 'int ({{.*}})' +// C-NEXT: |-NamespaceDecl [[ADDR_8:0x[a-z0-9]*]] prev [[ADDR_6]] line:15:80 __omp_declare_variant_scope +// C-NEXT: | |-original Namespace [[ADDR_4]] '__omp_declare_variant_scope' +// C-NEXT: | `-FunctionDecl [[ADDR_9:0x[a-z0-9]*]] col:5 also_before 'int ({{.*}})' +// C-NEXT: |-FunctionDecl [[ADDR_10:0x[a-z0-9]*]] prev [[ADDR_7]] line:19:5 used also_after 'int ({{.*}})' +// C-NEXT: | `-CompoundStmt [[ADDR_11:0x[a-z0-9]*]] +// C-NEXT: | `-ReturnStmt [[ADDR_12:0x[a-z0-9]*]] +// C-NEXT: | `-IntegerLiteral [[ADDR_13:0x[a-z0-9]*]] 'int' 0 +// C-NEXT: `-FunctionDecl [[ADDR_14:0x[a-z0-9]*]] line:23:5 test 'int ({{.*}})' +// C-NEXT: `-CompoundStmt [[ADDR_15:0x[a-z0-9]*]] +// C-NEXT: `-ReturnStmt [[ADDR_16:0x[a-z0-9]*]] +// C-NEXT: `-BinaryOperator [[ADDR_17:0x[a-z0-9]*]] 'int' '+' +// C-NEXT: |-CallExpr [[ADDR_18:0x[a-z0-9]*]] 'int' +// C-NEXT: | `-ImplicitCastExpr [[ADDR_19:0x[a-z0-9]*]] 'int (*)({{.*}})' +// C-NEXT: | `-DeclRefExpr [[ADDR_20:0x[a-z0-9]*]] 'int ({{.*}})' Function [[ADDR_10]] 'also_after' 'int ({{.*}})' +// C-NEXT: `-CallExpr [[ADDR_21:0x[a-z0-9]*]] 'int' +// C-NEXT: `-ImplicitCastExpr [[ADDR_22:0x[a-z0-9]*]] 'int (*)({{.*}})' +// C-NEXT: `-DeclRefExpr [[ADDR_23:0x[a-z0-9]*]] 'int ({{.*}})' Function [[ADDR_0]] 'also_before' 'int ({{.*}})' diff --git a/clang/test/OpenMP/begin-declare-variant_elided_range_withouth_end.c b/clang/test/OpenMP/begin-declare-variant_elided_range_withouth_end.c new file mode 100644 --- /dev/null +++ b/clang/test/OpenMP/begin-declare-variant_elided_range_withouth_end.c @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp -x c -std=c99 -fms-extensions -Wno-pragma-pack %s +// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp-simd -x c -std=c99 -fms-extensions -Wno-pragma-pack %s + +// TODO: Issue an eror message +// expected-no-diagnostics +#pragma omp begin declare variant match(device={kind(cpu)}) +// The matching end is missing. Since the device clause is matching we will +// emit and error. +int also_before(void) { + return 0; +} + +#pragma omp begin declare variant match(device={kind(gpu)}) +int also_after(void) { + return 2; +} +int also_before(void) { + return 2; +} +#pragma omp end declare variant + + +#pragma omp begin declare variant match(device={kind(fpga)}) + +This text is never parsed! + +#pragma omp end declare variant + +int also_after(void) { + return 0; +} + +int test() { + return also_after() + also_before(); +} diff --git a/clang/test/OpenMP/begin-declare-variant_using_messages.cpp b/clang/test/OpenMP/begin-declare-variant_using_messages.cpp new file mode 100644 --- /dev/null +++ b/clang/test/OpenMP/begin-declare-variant_using_messages.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s | FileCheck %s + +namespace BEFORE_AND_1 { +void before_and_1(); +} +namespace AFTER_AND_2 { +void after_and_2(); // expected-note {{'AFTER_AND_2::after_and_2' declared here}} expected-note {{'AFTER_AND_2::after_and_2' declared here}} expected-note {{'AFTER_AND_2::after_and_2' declared here}} +} +namespace ONLY_1 { +void only_1(); // expected-note {{'ONLY_1::only_1' declared here}} expected-note {{'ONLY_1::only_1' declared here}} +} +namespace BEFORE_1_AND_2 { +void before_1_and_2(); +} + +using BEFORE_1_AND_2::before_1_and_2; +using BEFORE_AND_1::before_and_1; + +void test_before() { + before_and_1(); + after_and_2(); // expected-error {{use of undeclared identifier 'after_and_2'; did you mean 'AFTER_AND_2::after_and_2'?}} + only_1(); // expected-error {{use of undeclared identifier 'only_1'; did you mean 'ONLY_1::only_1'?}} + before_1_and_2(); +} + +#pragma omp begin declare variant match(implementation = {vendor(llvm)}) +using BEFORE_1_AND_2::before_1_and_2; +using BEFORE_AND_1::before_and_1; +using ONLY_1::only_1; +void test_1() { + before_and_1(); + after_and_2(); // expected-error {{use of undeclared identifier 'after_and_2'; did you mean 'AFTER_AND_2::after_and_2'?}} + only_1(); + before_1_and_2(); +} +#pragma omp end declare variant + +#pragma omp begin declare variant match(implementation = {vendor(llvm)}) +using AFTER_AND_2::after_and_2; +using BEFORE_1_AND_2::before_1_and_2; +void test_2() { + before_and_1(); + after_and_2(); + only_1(); + before_1_and_2(); +} +#pragma omp end declare variant + +void test_after() { + before_and_1(); + after_and_2(); // expected-error {{use of undeclared identifier 'after_and_2'; did you mean 'AFTER_AND_2::after_and_2'?}} + only_1(); // expected-error {{use of undeclared identifier 'only_1'; did you mean 'ONLY_1::only_1'?}} + before_1_and_2(); +} + +using AFTER_AND_2::after_and_2; + +// Make sure: +// - we do not see the ast nodes for the gpu kind +// - we do not choke on the text in the kind(fpga) guarded scopes +// - we pick the right cbefore_1_and_2ees diff --git a/clang/test/OpenMP/declare_variant_begin_messages.c b/clang/test/OpenMP/declare_variant_begin_messages.c --- a/clang/test/OpenMP/declare_variant_begin_messages.c +++ b/clang/test/OpenMP/declare_variant_begin_messages.c @@ -4,11 +4,11 @@ #pragma omp begin // expected-error {{expected an OpenMP directive}} -#pragma omp end declare variant +#pragma omp end declare variant // expected-error {{expected '#pragma omp begin declare variant' to match this stray `#pragma omp end delcare variant`}} #pragma omp begin declare // expected-error {{expected an OpenMP directive}} -#pragma omp end declare variant +#pragma omp end declare variant // expected-error {{expected '#pragma omp begin declare variant' to match this stray `#pragma omp end delcare variant`}} #pragma omp begin variant // expected-error {{expected an OpenMP directive}} -#pragma omp end declare variant +#pragma omp end declare variant // expected-error {{expected '#pragma omp begin declare variant' to match this stray `#pragma omp end delcare variant`}} #pragma omp variant begin // expected-error {{expected an OpenMP directive}} #pragma omp declare variant end // expected-error {{function declaration is expected after 'declare variant' directive}} #pragma omp begin declare variant // expected-error {{expected 'match' clause on 'omp declare variant' directive}} @@ -33,7 +33,7 @@ #pragma omp end declare variant #pragma omp begin declare variant match(xxx=yyy) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} #pragma omp end declare variant -#pragma omp begin declare variant match(xxx=yyy}) // expected-error {{expected ')'}} expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}} +#pragma omp begin declare variant match(xxx=yyy}) // expected-error {{expected ')'}} expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-warning {{extra tokens at the end of '#pragma omp begin declare variant' are ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}} #pragma omp end declare variant #pragma omp begin declare variant match(xxx={) // expected-error {{expected ')'}} expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}} #pragma omp end declare variant @@ -43,7 +43,7 @@ #pragma omp end declare variant #pragma omp begin declare variant match(xxx={vvv} xxx) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} #pragma omp end declare variant -#pragma omp begin declare variant match(xxx={vvv}) xxx // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +#pragma omp begin declare variant match(xxx={vvv}) xxx // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-warning {{extra tokens at the end of '#pragma omp begin declare variant' are ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} #pragma omp end declare variant #pragma omp begin declare variant match(implementation={xxx}) // expected-warning {{'xxx' is not a valid context selector for the context set 'implementation'; selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} #pragma omp end declare variant