From: Douglas Gregor Date: Mon, 12 Apr 2010 23:19:01 +0000 (+0000) Subject: Improve source-location information for C++ conversion functions, by X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=05baacbfd67017b2724f3e0503fd23609f5d32bc;p=clang Improve source-location information for C++ conversion functions, by copying the type location information from the conversion-type-id into the type location information for the function type. Do something similar for constructors and destructors, by giving their "void" return type source-location information. In all of these cases, we previously left this type-source information uninitialized, which led to various unfortunate crashes. We still aren't tracking good source-location information for the actual names. That's PR6357. John, please check my sanity on this. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101088 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index adae0faa71..5110515366 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -704,7 +704,8 @@ public: QualType GetTypeForDeclarator(Declarator &D, Scope *S, TypeSourceInfo **TInfo = 0, TagDecl **OwnedDecl = 0); - TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T); + TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, + TypeSourceInfo *ReturnTypeInfo); /// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo. QualType CreateLocInfoType(QualType T, TypeSourceInfo *TInfo); DeclarationName GetNameForDeclarator(Declarator &D); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 4358640029..005bc4ad99 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -922,7 +922,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // Determine the type of the declarator. Not all forms of declarator // have a type. QualType T; - + TypeSourceInfo *ReturnTypeInfo = 0; + llvm::SmallVector FnAttrsFromDeclSpec; switch (D.getName().getKind()) { @@ -948,12 +949,20 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // Constructors and destructors don't have return types. Use // "void" instead. T = Context.VoidTy; + + // FIXME: Keep track of source location information within the constructor + // or destructor name. + if (TInfo) + ReturnTypeInfo = Context.getTrivialTypeSourceInfo(T, + D.getName().StartLocation); break; case UnqualifiedId::IK_ConversionFunctionId: // The result type of a conversion function is the type that it // converts to. - T = GetTypeFromParser(D.getName().ConversionFunctionId); + // FIXME: Keep track of the location of the 'operator' keyword? + T = GetTypeFromParser(D.getName().ConversionFunctionId, + TInfo? &ReturnTypeInfo : 0); break; } @@ -1356,7 +1365,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, if (D.isInvalidType()) *TInfo = 0; else - *TInfo = GetTypeSourceInfoForDeclarator(D, T); + *TInfo = GetTypeSourceInfoForDeclarator(D, T, ReturnTypeInfo); } return T; @@ -1541,8 +1550,14 @@ namespace { /// \brief Create and instantiate a TypeSourceInfo with type source information. /// /// \param T QualType referring to the type as written in source code. +/// +/// \param ReturnTypeInfo For declarators whose return type does not show +/// up in the normal place in the declaration specifiers (such as a C++ +/// conversion function), this pointer will refer to a type source information +/// for that return type. TypeSourceInfo * -Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T) { +Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, + TypeSourceInfo *ReturnTypeInfo) { TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T); UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc(); @@ -1552,7 +1567,18 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T) { } TypeSpecLocFiller(D.getDeclSpec()).Visit(CurrTL); - + + // We have source information for the return type that was not in the + // declaration specifiers; copy that information into the current type + // location so that it will be retained. This occurs, for example, with + // a C++ conversion function, where the return type occurs within the + // declarator-id rather than in the declaration specifiers. + if (ReturnTypeInfo && D.getDeclSpec().getTypeSpecType() == TST_unspecified) { + TypeLoc TL = ReturnTypeInfo->getTypeLoc(); + assert(TL.getFullDataSize() == CurrTL.getFullDataSize()); + memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize()); + } + return TInfo; } diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp index bca75c0b2f..381cd60d40 100644 --- a/test/SemaCXX/conversion-function.cpp +++ b/test/SemaCXX/conversion-function.cpp @@ -131,3 +131,37 @@ private: A1 f() { return "Hello"; // expected-error{{invokes deleted copy constructor}} } + +namespace source_locations { + template + struct sneaky_int { + typedef int type; + }; + + template + struct A { }; + + template + struct A : A { }; + + struct E { + template + operator A::type>&() const; // expected-note{{candidate function}} + }; + + void f() { + A &af = E(); // expected-error{{no viable conversion}} + A &af2 = E(); + const A &caf2 = E(); + } + + // Check + template + struct E2 { + operator T + * // expected-error{{pointer to a reference}} + () const; + }; + + E2 e2i; // expected-note{{in instantiation}} +}