forked from OSchip/llvm-project
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. llvm-svn: 101088
This commit is contained in:
parent
ebbd05f8ce
commit
5c0066f1cf
|
@ -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);
|
||||
|
|
|
@ -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<DelayedAttribute,4> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -131,3 +131,37 @@ private:
|
|||
A1 f() {
|
||||
return "Hello"; // expected-error{{invokes deleted copy constructor}}
|
||||
}
|
||||
|
||||
namespace source_locations {
|
||||
template<typename T>
|
||||
struct sneaky_int {
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct A { };
|
||||
|
||||
template<typename T>
|
||||
struct A<T, T> : A<T, int> { };
|
||||
|
||||
struct E {
|
||||
template<typename T>
|
||||
operator A<T, typename sneaky_int<T>::type>&() const; // expected-note{{candidate function}}
|
||||
};
|
||||
|
||||
void f() {
|
||||
A<float, float> &af = E(); // expected-error{{no viable conversion}}
|
||||
A<float, int> &af2 = E();
|
||||
const A<float, int> &caf2 = E();
|
||||
}
|
||||
|
||||
// Check
|
||||
template<typename T>
|
||||
struct E2 {
|
||||
operator T
|
||||
* // expected-error{{pointer to a reference}}
|
||||
() const;
|
||||
};
|
||||
|
||||
E2<int&> e2i; // expected-note{{in instantiation}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue