Author: Sirraide Date: 2024-09-26T03:24:53+02:00 New Revision: f4fa16f14b3ee7da244687e4a138a5a6df3e1a48
URL: https://github.com/llvm/llvm-project/commit/f4fa16f14b3ee7da244687e4a138a5a6df3e1a48 DIFF: https://github.com/llvm/llvm-project/commit/f4fa16f14b3ee7da244687e4a138a5a6df3e1a48.diff LOG: [Clang] Bugfixes and improved support for `AttributedType`s in lambdas (#85325) This fixes a crash when we attempt to instantiate a lambda with an `AnnotatedType`, refactors the code that handles transforming the function type of a lambda, and improves source fidelity for lambda function types. This fixes #85120 and fixes #85154. --------- Co-authored-by: Yuxuan Chen <y...@meta.com> Co-authored-by: Doug Wyatt <dwy...@apple.com> Added: clang/test/SemaCXX/lambda-attributes.cpp Modified: clang/include/clang/AST/ASTContext.h clang/include/clang/Sema/Template.h clang/lib/AST/ASTContext.cpp clang/lib/Sema/SemaTemplateInstantiate.cpp clang/lib/Sema/TreeTransform.h clang/test/SemaCXX/lambda-conversion-op-cc.cpp Removed: ################################################################################ diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 1984310df0442e..fbf38ab4da6c8c 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -253,7 +253,7 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable llvm::FoldingSet<BitIntType> BitIntTypes; mutable llvm::ContextualFoldingSet<DependentBitIntType, ASTContext &> DependentBitIntTypes; - llvm::FoldingSet<BTFTagAttributedType> BTFTagAttributedTypes; + mutable llvm::FoldingSet<BTFTagAttributedType> BTFTagAttributedTypes; llvm::FoldingSet<HLSLAttributedResourceType> HLSLAttributedResourceTypes; mutable llvm::FoldingSet<CountAttributedType> CountAttributedTypes; @@ -1369,10 +1369,21 @@ class ASTContext : public RefCountedBase<ASTContext> { /// calling T.withConst(). QualType getConstType(QualType T) const { return T.withConst(); } + /// Rebuild a type, preserving any existing type sugar. For function types, + /// you probably want to just use \c adjustFunctionResultType and friends + /// instead. + QualType adjustType(QualType OldType, + llvm::function_ref<QualType(QualType)> Adjust) const; + /// Change the ExtInfo on a function type. const FunctionType *adjustFunctionType(const FunctionType *Fn, FunctionType::ExtInfo EInfo); + /// Change the result type of a function type, preserving sugar such as + /// attributed types. + QualType adjustFunctionResultType(QualType FunctionType, + QualType NewResultType); + /// Adjust the given function result type. CanQualType getCanonicalFunctionResultType(QualType ResultType) const; @@ -1702,7 +1713,7 @@ class ASTContext : public RefCountedBase<ASTContext> { QualType equivalentType) const; QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr, - QualType Wrapped); + QualType Wrapped) const; QualType getHLSLAttributedResourceType( QualType Wrapped, QualType Contained, diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index 0340c23fd170d6..fe27290efdbfc5 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -411,6 +411,11 @@ enum class TemplateSubstitutionKind : char { /// lookup will search our outer scope. bool CombineWithOuterScope; + /// Whether this scope is being used to instantiate a lambda expression, + /// in which case it should be reused for instantiating the lambda's + /// FunctionProtoType. + bool InstantiatingLambda = false; + /// If non-NULL, the template parameter pack that has been /// partially substituted per C++0x [temp.arg.explicit]p9. NamedDecl *PartiallySubstitutedPack = nullptr; @@ -425,9 +430,11 @@ enum class TemplateSubstitutionKind : char { unsigned NumArgsInPartiallySubstitutedPack; public: - LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false) + LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false, + bool InstantiatingLambda = false) : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope), - CombineWithOuterScope(CombineWithOuterScope) { + CombineWithOuterScope(CombineWithOuterScope), + InstantiatingLambda(InstantiatingLambda) { SemaRef.CurrentInstantiationScope = this; } @@ -553,6 +560,9 @@ enum class TemplateSubstitutionKind : char { /// Determine whether D is a pack expansion created in this scope. bool isLocalPackExpansion(const Decl *D); + + /// Determine whether this scope is for instantiating a lambda. + bool isLambda() const { return InstantiatingLambda; } }; class TemplateDeclInstantiator diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index fd8aa8de79b49f..cda8b02cc8499a 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3535,6 +3535,50 @@ QualType ASTContext::getCountAttributedType( return QualType(CATy, 0); } +QualType +ASTContext::adjustType(QualType Orig, + llvm::function_ref<QualType(QualType)> Adjust) const { + switch (Orig->getTypeClass()) { + case Type::Attributed: { + const auto *AT = dyn_cast<AttributedType>(Orig); + return getAttributedType(AT->getAttrKind(), + adjustType(AT->getModifiedType(), Adjust), + adjustType(AT->getEquivalentType(), Adjust)); + } + + case Type::BTFTagAttributed: { + const auto *BTFT = dyn_cast<BTFTagAttributedType>(Orig); + return getBTFTagAttributedType(BTFT->getAttr(), + adjustType(BTFT->getWrappedType(), Adjust)); + } + + case Type::Elaborated: { + const auto *ET = cast<ElaboratedType>(Orig); + return getElaboratedType(ET->getKeyword(), ET->getQualifier(), + adjustType(ET->getNamedType(), Adjust)); + } + + case Type::Paren: + return getParenType( + adjustType(cast<ParenType>(Orig)->getInnerType(), Adjust)); + + case Type::Adjusted: { + const auto *AT = cast<AdjustedType>(Orig); + return getAdjustedType(AT->getOriginalType(), + adjustType(AT->getAdjustedType(), Adjust)); + } + + case Type::MacroQualified: { + const auto *MQT = cast<MacroQualifiedType>(Orig); + return getMacroQualifiedType(adjustType(MQT->getUnderlyingType(), Adjust), + MQT->getMacroIdentifier()); + } + + default: + return Adjust(Orig); + } +} + const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, FunctionType::ExtInfo Info) { if (T->getExtInfo() == Info) @@ -3553,13 +3597,23 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, return cast<FunctionType>(Result.getTypePtr()); } +QualType ASTContext::adjustFunctionResultType(QualType FunctionType, + QualType ResultType) { + return adjustType(FunctionType, [&](QualType Orig) { + if (const auto *FNPT = Orig->getAs<FunctionNoProtoType>()) + return getFunctionNoProtoType(ResultType, FNPT->getExtInfo()); + + const auto *FPT = Orig->castAs<FunctionProtoType>(); + return getFunctionType(ResultType, FPT->getParamTypes(), + FPT->getExtProtoInfo()); + }); +} + void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType) { FD = FD->getMostRecentDecl(); while (true) { - const auto *FPT = FD->getType()->castAs<FunctionProtoType>(); - FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - FD->setType(getFunctionType(ResultType, FPT->getParamTypes(), EPI)); + FD->setType(adjustFunctionResultType(FD->getType(), ResultType)); if (FunctionDecl *Next = FD->getPreviousDecl()) FD = Next; else @@ -3575,30 +3629,11 @@ void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD, /// and preserved. Other type sugar (for instance, typedefs) is not. QualType ASTContext::getFunctionTypeWithExceptionSpec( QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI) const { - // Might have some parens. - if (const auto *PT = dyn_cast<ParenType>(Orig)) - return getParenType( - getFunctionTypeWithExceptionSpec(PT->getInnerType(), ESI)); - - // Might be wrapped in a macro qualified type. - if (const auto *MQT = dyn_cast<MacroQualifiedType>(Orig)) - return getMacroQualifiedType( - getFunctionTypeWithExceptionSpec(MQT->getUnderlyingType(), ESI), - MQT->getMacroIdentifier()); - - // Might have a calling-convention attribute. - if (const auto *AT = dyn_cast<AttributedType>(Orig)) - return getAttributedType( - AT->getAttrKind(), - getFunctionTypeWithExceptionSpec(AT->getModifiedType(), ESI), - getFunctionTypeWithExceptionSpec(AT->getEquivalentType(), ESI)); - - // Anything else must be a function type. Rebuild it with the new exception - // specification. - const auto *Proto = Orig->castAs<FunctionProtoType>(); - return getFunctionType( - Proto->getReturnType(), Proto->getParamTypes(), - Proto->getExtProtoInfo().withExceptionSpec(ESI)); + return adjustType(Orig, [&](QualType Ty) { + const auto *Proto = Ty->castAs<FunctionProtoType>(); + return getFunctionType(Proto->getReturnType(), Proto->getParamTypes(), + Proto->getExtProtoInfo().withExceptionSpec(ESI)); + }); } bool ASTContext::hasSameFunctionTypeIgnoringExceptionSpec(QualType T, @@ -5165,7 +5200,7 @@ QualType ASTContext::getAttributedType(attr::Kind attrKind, } QualType ASTContext::getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr, - QualType Wrapped) { + QualType Wrapped) const { llvm::FoldingSetNodeID ID; BTFTagAttributedType::Profile(ID, Wrapped, BTFAttr); diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 55f38743e2768e..fd51fa4afcacbf 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1677,7 +1677,8 @@ namespace { // Lambdas have already been processed inside their eval contexts. if (SemaRef.RebuildingImmediateInvocation) return E; - LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true); + LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true, + /*InstantiatingLambda=*/true); Sema::ConstraintEvalRAII<TemplateInstantiator> RAII(*this); return inherited::TransformLambdaExpr(E); @@ -2432,8 +2433,18 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB, CXXRecordDecl *ThisContext, Qualifiers ThisTypeQuals, Fn TransformExceptionSpec) { - // We need a local instantiation scope for this function prototype. - LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true); + // If this is a lambda, the transformation MUST be done in the + // CurrentInstantiationScope since it introduces a mapping of + // the original to the newly created transformed parameters. + // + // In that case, TemplateInstantiator::TransformLambdaExpr will + // have already pushed a scope for this prototype, so don't create + // a second one. + LocalInstantiationScope *Current = getSema().CurrentInstantiationScope; + std::optional<LocalInstantiationScope> Scope; + if (!Current || !Current->isLambda()) + Scope.emplace(SemaRef, /*CombineWithOuterScope=*/true); + return inherited::TransformFunctionProtoType( TLB, TL, ThisContext, ThisTypeQuals, TransformExceptionSpec); } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 95ded5e59a9fa7..91cb980ee26b26 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -684,10 +684,6 @@ class TreeTransform { Qualifiers ThisTypeQuals, Fn TransformExceptionSpec); - template <typename Fn> - QualType TransformAttributedType(TypeLocBuilder &TLB, AttributedTypeLoc TL, - Fn TransformModifiedType); - bool TransformExceptionSpec(SourceLocation Loc, FunctionProtoType::ExceptionSpecInfo &ESI, SmallVectorImpl<QualType> &Exceptions, @@ -7373,11 +7369,10 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB, } template <typename Derived> -template <typename Fn> -QualType TreeTransform<Derived>::TransformAttributedType( - TypeLocBuilder &TLB, AttributedTypeLoc TL, Fn TransformModifiedTypeFn) { +QualType TreeTransform<Derived>::TransformAttributedType(TypeLocBuilder &TLB, + AttributedTypeLoc TL) { const AttributedType *oldType = TL.getTypePtr(); - QualType modifiedType = TransformModifiedTypeFn(TLB, TL.getModifiedLoc()); + QualType modifiedType = getDerived().TransformType(TLB, TL.getModifiedLoc()); if (modifiedType.isNull()) return QualType(); @@ -7392,12 +7387,27 @@ QualType TreeTransform<Derived>::TransformAttributedType( // FIXME: dependent operand expressions? if (getDerived().AlwaysRebuild() || modifiedType != oldType->getModifiedType()) { - TypeLocBuilder AuxiliaryTLB; - AuxiliaryTLB.reserve(TL.getFullDataSize()); - QualType equivalentType = - getDerived().TransformType(AuxiliaryTLB, TL.getEquivalentTypeLoc()); - if (equivalentType.isNull()) - return QualType(); + // If the equivalent type is equal to the modified type, we don't want to + // transform it as well because: + // + // 1. The transformation would yield the same result and is therefore + // superfluous, and + // + // 2. Transforming the same type twice can cause problems, e.g. if it + // is a FunctionProtoType, we may end up instantiating the function + // parameters twice, which causes an assertion since the parameters + // are already bound to their counterparts in the template for this + // instantiation. + // + QualType equivalentType = modifiedType; + if (TL.getModifiedLoc().getType() != TL.getEquivalentTypeLoc().getType()) { + TypeLocBuilder AuxiliaryTLB; + AuxiliaryTLB.reserve(TL.getFullDataSize()); + equivalentType = + getDerived().TransformType(AuxiliaryTLB, TL.getEquivalentTypeLoc()); + if (equivalentType.isNull()) + return QualType(); + } // Check whether we can add nullability; it is only represented as // type sugar, and therefore cannot be diagnosed in any other way. @@ -7421,15 +7431,6 @@ QualType TreeTransform<Derived>::TransformAttributedType( return result; } -template <typename Derived> -QualType TreeTransform<Derived>::TransformAttributedType(TypeLocBuilder &TLB, - AttributedTypeLoc TL) { - return getDerived().TransformAttributedType( - TLB, TL, [&](TypeLocBuilder &TLB, TypeLoc ModifiedLoc) -> QualType { - return getDerived().TransformType(TLB, ModifiedLoc); - }); -} - template <typename Derived> QualType TreeTransform<Derived>::TransformCountAttributedType( TypeLocBuilder &TLB, CountAttributedTypeLoc TL) { @@ -14774,63 +14775,29 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { TPL->containsUnexpandedParameterPack(); } - // Transform the type of the original lambda's call operator. - // The transformation MUST be done in the CurrentInstantiationScope since - // it introduces a mapping of the original to the newly created - // transformed parameters. - TypeSourceInfo *NewCallOpTSI = nullptr; - { - auto OldCallOpTypeLoc = - E->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); - - auto TransformFunctionProtoTypeLoc = - [this](TypeLocBuilder &TLB, FunctionProtoTypeLoc FPTL) -> QualType { - SmallVector<QualType, 4> ExceptionStorage; - return this->TransformFunctionProtoType( - TLB, FPTL, nullptr, Qualifiers(), - [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) { - return TransformExceptionSpec(FPTL.getBeginLoc(), ESI, - ExceptionStorage, Changed); - }); - }; - - QualType NewCallOpType; - TypeLocBuilder NewCallOpTLBuilder; - - if (auto ATL = OldCallOpTypeLoc.getAs<AttributedTypeLoc>()) { - NewCallOpType = this->TransformAttributedType( - NewCallOpTLBuilder, ATL, - [&](TypeLocBuilder &TLB, TypeLoc TL) -> QualType { - return TransformFunctionProtoTypeLoc( - TLB, TL.castAs<FunctionProtoTypeLoc>()); - }); - } else { - auto FPTL = OldCallOpTypeLoc.castAs<FunctionProtoTypeLoc>(); - NewCallOpType = TransformFunctionProtoTypeLoc(NewCallOpTLBuilder, FPTL); - } - - if (NewCallOpType.isNull()) - return ExprError(); - LSI->ContainsUnexpandedParameterPack |= - NewCallOpType->containsUnexpandedParameterPack(); - NewCallOpTSI = - NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType); - } + TypeLocBuilder NewCallOpTLBuilder; + TypeLoc OldCallOpTypeLoc = + E->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); + QualType NewCallOpType = + getDerived().TransformType(NewCallOpTLBuilder, OldCallOpTypeLoc); + if (NewCallOpType.isNull()) + return ExprError(); + LSI->ContainsUnexpandedParameterPack |= + NewCallOpType->containsUnexpandedParameterPack(); + TypeSourceInfo *NewCallOpTSI = + NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType); - ArrayRef<ParmVarDecl *> Params; - if (auto ATL = NewCallOpTSI->getTypeLoc().getAs<AttributedTypeLoc>()) { - Params = ATL.getModifiedLoc().castAs<FunctionProtoTypeLoc>().getParams(); - } else { - auto FPTL = NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>(); - Params = FPTL.getParams(); - } + // The type may be an AttributedType or some other kind of sugar; + // get the actual underlying FunctionProtoType. + auto FPTL = NewCallOpTSI->getTypeLoc().getAsAdjusted<FunctionProtoTypeLoc>(); + assert(FPTL && "Not a FunctionProtoType?"); getSema().CompleteLambdaCallOperator( NewCallOperator, E->getCallOperator()->getLocation(), E->getCallOperator()->getInnerLocStart(), E->getCallOperator()->getTrailingRequiresClause(), NewCallOpTSI, E->getCallOperator()->getConstexprKind(), - E->getCallOperator()->getStorageClass(), Params, + E->getCallOperator()->getStorageClass(), FPTL.getParams(), E->hasExplicitResultType()); getDerived().transformAttrs(E->getCallOperator(), NewCallOperator); diff --git a/clang/test/SemaCXX/lambda-attributes.cpp b/clang/test/SemaCXX/lambda-attributes.cpp new file mode 100644 index 00000000000000..799649719cf42b --- /dev/null +++ b/clang/test/SemaCXX/lambda-attributes.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++23 -fsyntax-only -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -std=c++23 -triple x86_64-pc-linux -emit-pch -o %t %s +// RUN: %clang_cc1 -x c++ -std=c++23 -triple x86_64-pc-linux -include-pch %t -ast-dump-all /dev/null | FileCheck %s +// expected-no-diagnostics + +// Check that we both don't crash on transforming FunctionProtoType's +// wrapped in type sugar and that we don't drop it when performing +// instantiations either. + +#define PRESERVE __attribute__((preserve_most)) + +// Skip to the instantiation of f(). +// CHECK: FunctionDecl {{.*}} f 'void ()' implicit_instantiation +template <typename T> +void f() { + // CHECK: CXXMethodDecl {{.*}} operator() 'void (int) const __attribute__((preserve_most))':'void (int) __attribute__((preserve_most)) const' implicit_instantiation + (void) [] (T) __attribute__((preserve_most)) { }; + + // CHECK: CXXMethodDecl {{.*}} operator() 'void (int) const {{\[}}[clang::annotate_type(...)]]':'void (int) const' implicit_instantiation + (void) [] (T) [[clang::annotate_type("foo")]] { }; + + // CHECK: CXXMethodDecl {{.*}} operator() 'void (int) const {{\[}}[clang::annotate_type(...)]] {{\[}}[clang::annotate_type(...)]] {{\[}}[clang::annotate_type(...)]]':'void (int) const' implicit_instantiation + (void) [] (T) [[clang::annotate_type("foo")]] + [[clang::annotate_type("foo")]] + [[clang::annotate_type("foo")]] { }; + + // CHECK: CXXMethodDecl {{.*}} operator() 'void (int) const __attribute__((preserve_most)) {{\[}}[clang::annotate_type(...)]]':'void (int) __attribute__((preserve_most)) const' implicit_instantiation + (void) [] (T) __attribute__((preserve_most)) + [[clang::annotate_type("foo")]] { }; + + // CHECK: CXXMethodDecl {{.*}} operator() 'void (int) const __attribute__((cdecl)) {{\[}}[clang::annotate_type(...)]]':'void (int) const' implicit_instantiation + (void) [] (T) __attribute__((cdecl)) + [[clang::annotate_type("foo")]] { }; + + // CHECK: CXXMethodDecl {{.*}} operator() 'void (int) const {{\[}}[clang::annotate_type(...)]]':'void (int) const' implicit_instantiation + (void) [] (T t) [[clang::annotate_type("foo", t)]] { }; + + // CHECK: CXXMethodDecl {{.*}} operator() 'void (int) const __attribute__((preserve_most)) {{\[}}[clang::annotate_type(...)]]':'void (int) __attribute__((preserve_most)) const' implicit_instantiation + (void) [] (T t) __attribute__((preserve_most)) + [[clang::annotate_type("foo", t, t, t, t)]] { }; + + // Check that the MacroQualifiedType is preserved. + // CHECK: CXXMethodDecl {{.*}} operator() 'PRESERVE void (int) __attribute__((preserve_most)) const':'void (int) __attribute__((preserve_most)) const' implicit_instantiation + (void) [] (T) PRESERVE { }; + + // CHECK: CXXMethodDecl {{.*}} operator() 'PRESERVE void (int) __attribute__((preserve_most)) const {{\[}}[clang::annotate_type(...)]]':'void (int) __attribute__((preserve_most)) const' implicit_instantiation + (void) [] (T) PRESERVE [[clang::annotate_type("foo")]] { }; + + // CHECK: CXXMethodDecl {{.*}} operator() 'void (int) const {{\[}}[clang::annotate_type(...)]]':'void (int) const' implicit_instantiation + (void) [] (T) [[clang::annotate_type("foo")]] { + // CHECK: CXXMethodDecl {{.*}} operator() 'PRESERVE void (int) __attribute__((preserve_most)) const {{\[}}[clang::annotate_type(...)]]':'void (int) __attribute__((preserve_most)) const' implicit_instantiation + auto l = []<typename U = T> (U u = {}) PRESERVE [[clang::annotate_type("foo", u)]] { }; + + // CHECK: DeclRefExpr {{.*}} 'PRESERVE void (int) __attribute__((preserve_most)) const {{\[}}[clang::annotate_type(...)]]':'void (int) __attribute__((preserve_most)) const' lvalue CXXMethod + l(); + }; +} + +void g() { + f<int>(); +} diff --git a/clang/test/SemaCXX/lambda-conversion-op-cc.cpp b/clang/test/SemaCXX/lambda-conversion-op-cc.cpp index 3632f8c8c80aaa..6d9f5d702e1329 100644 --- a/clang/test/SemaCXX/lambda-conversion-op-cc.cpp +++ b/clang/test/SemaCXX/lambda-conversion-op-cc.cpp @@ -44,19 +44,19 @@ void useage() { // CHECK: VarDecl {{.*}} vectorcall ' // CHECK: LambdaExpr - // CHECK: CXXMethodDecl {{.*}} operator() 'void (int, float, double) __attribute__((vectorcall)) const' + // CHECK: CXXMethodDecl {{.*}} operator() 'void (int, float, double) const __attribute__((vectorcall))':'void (int, float, double) __attribute__((vectorcall)) const' // CHECK: CXXConversionDecl {{.*}} operator void (*)(int, float, double) __attribute__((vectorcall)) 'void // CHECK: CXXMethodDecl {{.*}} __invoke 'void (int, float, double) __attribute__((vectorcall))' static inline // WIN32: VarDecl {{.*}} thiscall ' // WIN32: LambdaExpr - // WIN32: CXXMethodDecl {{.*}} operator() 'void (int, float, double) __attribute__((thiscall)) const' + // WIN32: CXXMethodDecl {{.*}} operator() 'void (int, float, double) const __attribute__((thiscall))':'void (int, float, double) __attribute__((thiscall)) const' // WIN32: CXXConversionDecl {{.*}} operator void (*)(int, float, double) 'void // WIN32: CXXMethodDecl {{.*}} __invoke 'void (int, float, double)' static inline // CHECK: VarDecl {{.*}} cdecl ' // CHECK: LambdaExpr - // CHECK: CXXMethodDecl {{.*}} operator() 'void (int, float, double) const' + // CHECK: CXXMethodDecl {{.*}} operator() 'void (int, float, double) const __attribute__((cdecl))':'void (int, float, double) const' // NODEF: CXXConversionDecl {{.*}} operator void (*)(int, float, double) 'void // NODEF: CXXMethodDecl {{.*}} __invoke 'void (int, float, double)' static inline // VECTDEF: CXXConversionDecl {{.*}} operator void (*)(int, float, double) __attribute__((vectorcall)) 'void @@ -108,8 +108,8 @@ void useage() { // CHECK: LambdaExpr // CHECK: FunctionTemplateDecl {{.*}} operator() // CHECK: CXXMethodDecl {{.*}} operator() 'auto (auto) __attribute__((vectorcall)) const' inline - // CHECK: CXXMethodDecl {{.*}} operator() 'void (char) __attribute__((vectorcall)) const' implicit_instantiation inline - // CHECK: CXXMethodDecl {{.*}} operator() 'void (int) __attribute__((vectorcall)) const' implicit_instantiation inline + // CHECK: CXXMethodDecl {{.*}} operator() 'void (char) const __attribute__((vectorcall))':'void (char) __attribute__((vectorcall)) const' implicit_instantiation inline + // CHECK: CXXMethodDecl {{.*}} operator() 'void (int) const __attribute__((vectorcall))':'void (int) __attribute__((vectorcall)) const' implicit_instantiation inline // CHECK: FunctionTemplateDecl {{.*}} operator auto (*)(type-parameter-0-0) __attribute__((vectorcall)) // LIN64: CXXConversionDecl {{.*}} operator auto (*)(type-parameter-0-0) __attribute__((vectorcall)) 'auto (*() const noexcept)(auto) __attribute__((vectorcall))' // LIN64: CXXConversionDecl {{.*}} operator auto (*)(char) __attribute__((vectorcall)) 'void (*() const noexcept)(char) __attribute__((vectorcall))' _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits