forked from OSchip/llvm-project
[Sema] Store a SourceRange for multi-token builtin types
Summary: clang-tidy's modernize-use-auto check uses the SourceRange of a TypeLoc when replacing the type with auto. This was producing the wrong result for multi-token builtin types like long long: -long long *ll = new long long(); +auto long *ll = new long long(); Reviewers: alexfh, hokein, rsmith, Prazek, aaron.ballman Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D25363 llvm-svn: 284885
This commit is contained in:
parent
8659d16631
commit
57c09c8e23
|
@ -512,7 +512,7 @@ private:
|
||||||
|
|
||||||
|
|
||||||
struct BuiltinLocInfo {
|
struct BuiltinLocInfo {
|
||||||
SourceLocation BuiltinLoc;
|
SourceRange BuiltinRange;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Wrapper for source info for builtin types.
|
/// \brief Wrapper for source info for builtin types.
|
||||||
|
@ -522,10 +522,19 @@ class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
|
||||||
BuiltinLocInfo> {
|
BuiltinLocInfo> {
|
||||||
public:
|
public:
|
||||||
SourceLocation getBuiltinLoc() const {
|
SourceLocation getBuiltinLoc() const {
|
||||||
return getLocalData()->BuiltinLoc;
|
return getLocalData()->BuiltinRange.getBegin();
|
||||||
}
|
}
|
||||||
void setBuiltinLoc(SourceLocation Loc) {
|
void setBuiltinLoc(SourceLocation Loc) {
|
||||||
getLocalData()->BuiltinLoc = Loc;
|
getLocalData()->BuiltinRange = Loc;
|
||||||
|
}
|
||||||
|
void expandBuiltinRange(SourceRange Range) {
|
||||||
|
SourceRange &BuiltinRange = getLocalData()->BuiltinRange;
|
||||||
|
if (!BuiltinRange.getBegin().isValid()) {
|
||||||
|
BuiltinRange = Range;
|
||||||
|
} else {
|
||||||
|
BuiltinRange.setBegin(std::min(Range.getBegin(), BuiltinRange.getBegin()));
|
||||||
|
BuiltinRange.setEnd(std::max(Range.getEnd(), BuiltinRange.getEnd()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLocation getNameLoc() const { return getBuiltinLoc(); }
|
SourceLocation getNameLoc() const { return getBuiltinLoc(); }
|
||||||
|
@ -554,7 +563,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceRange getLocalSourceRange() const {
|
SourceRange getLocalSourceRange() const {
|
||||||
return SourceRange(getBuiltinLoc(), getBuiltinLoc());
|
return getLocalData()->BuiltinRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeSpecifierSign getWrittenSignSpec() const {
|
TypeSpecifierSign getWrittenSignSpec() const {
|
||||||
|
|
|
@ -380,7 +380,8 @@ private:
|
||||||
SourceRange Range;
|
SourceRange Range;
|
||||||
|
|
||||||
SourceLocation StorageClassSpecLoc, ThreadStorageClassSpecLoc;
|
SourceLocation StorageClassSpecLoc, ThreadStorageClassSpecLoc;
|
||||||
SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc, AltiVecLoc;
|
SourceRange TSWRange;
|
||||||
|
SourceLocation TSCLoc, TSSLoc, TSTLoc, AltiVecLoc;
|
||||||
/// TSTNameLoc - If TypeSpecType is any of class, enum, struct, union,
|
/// TSTNameLoc - If TypeSpecType is any of class, enum, struct, union,
|
||||||
/// typename, then this is the location of the named type (if present);
|
/// typename, then this is the location of the named type (if present);
|
||||||
/// otherwise, it is the same as TSTLoc. Hence, the pair TSTLoc and
|
/// otherwise, it is the same as TSTLoc. Hence, the pair TSTLoc and
|
||||||
|
@ -503,7 +504,8 @@ public:
|
||||||
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
|
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
|
||||||
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
|
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
|
||||||
|
|
||||||
SourceLocation getTypeSpecWidthLoc() const { return TSWLoc; }
|
SourceLocation getTypeSpecWidthLoc() const { return TSWRange.getBegin(); }
|
||||||
|
SourceRange getTypeSpecWidthRange() const { return TSWRange; }
|
||||||
SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; }
|
SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; }
|
||||||
SourceLocation getTypeSpecSignLoc() const { return TSSLoc; }
|
SourceLocation getTypeSpecSignLoc() const { return TSSLoc; }
|
||||||
SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; }
|
SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; }
|
||||||
|
|
|
@ -610,14 +610,16 @@ bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
|
||||||
const char *&PrevSpec,
|
const char *&PrevSpec,
|
||||||
unsigned &DiagID,
|
unsigned &DiagID,
|
||||||
const PrintingPolicy &Policy) {
|
const PrintingPolicy &Policy) {
|
||||||
// Overwrite TSWLoc only if TypeSpecWidth was unspecified, so that
|
// Overwrite TSWRange.Begin only if TypeSpecWidth was unspecified, so that
|
||||||
// for 'long long' we will keep the source location of the first 'long'.
|
// for 'long long' we will keep the source location of the first 'long'.
|
||||||
if (TypeSpecWidth == TSW_unspecified)
|
if (TypeSpecWidth == TSW_unspecified)
|
||||||
TSWLoc = Loc;
|
TSWRange.setBegin(Loc);
|
||||||
// Allow turning long -> long long.
|
// Allow turning long -> long long.
|
||||||
else if (W != TSW_longlong || TypeSpecWidth != TSW_long)
|
else if (W != TSW_longlong || TypeSpecWidth != TSW_long)
|
||||||
return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
|
return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
|
||||||
TypeSpecWidth = W;
|
TypeSpecWidth = W;
|
||||||
|
// Remember location of the last 'long'
|
||||||
|
TSWRange.setEnd(Loc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -997,9 +999,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
|
||||||
TypeQualifiers)) {
|
TypeQualifiers)) {
|
||||||
const unsigned NumLocs = 9;
|
const unsigned NumLocs = 9;
|
||||||
SourceLocation ExtraLocs[NumLocs] = {
|
SourceLocation ExtraLocs[NumLocs] = {
|
||||||
TSWLoc, TSCLoc, TSSLoc, AltiVecLoc,
|
TSWRange.getBegin(), TSCLoc, TSSLoc,
|
||||||
TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc, TQ_unalignedLoc
|
AltiVecLoc, TQ_constLoc, TQ_restrictLoc,
|
||||||
};
|
TQ_volatileLoc, TQ_atomicLoc, TQ_unalignedLoc};
|
||||||
FixItHint Hints[NumLocs];
|
FixItHint Hints[NumLocs];
|
||||||
SourceLocation FirstLoc;
|
SourceLocation FirstLoc;
|
||||||
for (unsigned I = 0; I != NumLocs; ++I) {
|
for (unsigned I = 0; I != NumLocs; ++I) {
|
||||||
|
@ -1041,8 +1043,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
|
||||||
// Only 'short' and 'long long' are valid with vector bool. (PIM 2.1)
|
// Only 'short' and 'long long' are valid with vector bool. (PIM 2.1)
|
||||||
if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short) &&
|
if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short) &&
|
||||||
(TypeSpecWidth != TSW_longlong))
|
(TypeSpecWidth != TSW_longlong))
|
||||||
S.Diag(TSWLoc, diag::err_invalid_vector_bool_decl_spec)
|
S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_bool_decl_spec)
|
||||||
<< getSpecifierName((TSW)TypeSpecWidth);
|
<< getSpecifierName((TSW)TypeSpecWidth);
|
||||||
|
|
||||||
// vector bool long long requires VSX support or ZVector.
|
// vector bool long long requires VSX support or ZVector.
|
||||||
if ((TypeSpecWidth == TSW_longlong) &&
|
if ((TypeSpecWidth == TSW_longlong) &&
|
||||||
|
@ -1059,7 +1061,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
|
||||||
// vector long double and vector long long double are never allowed.
|
// vector long double and vector long long double are never allowed.
|
||||||
// vector double is OK for Power7 and later, and ZVector.
|
// vector double is OK for Power7 and later, and ZVector.
|
||||||
if (TypeSpecWidth == TSW_long || TypeSpecWidth == TSW_longlong)
|
if (TypeSpecWidth == TSW_long || TypeSpecWidth == TSW_longlong)
|
||||||
S.Diag(TSWLoc, diag::err_invalid_vector_long_double_decl_spec);
|
S.Diag(TSWRange.getBegin(),
|
||||||
|
diag::err_invalid_vector_long_double_decl_spec);
|
||||||
else if (!S.Context.getTargetInfo().hasFeature("vsx") &&
|
else if (!S.Context.getTargetInfo().hasFeature("vsx") &&
|
||||||
!S.getLangOpts().ZVector)
|
!S.getLangOpts().ZVector)
|
||||||
S.Diag(TSTLoc, diag::err_invalid_vector_double_decl_spec);
|
S.Diag(TSTLoc, diag::err_invalid_vector_double_decl_spec);
|
||||||
|
@ -1070,10 +1073,11 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
|
||||||
} else if (TypeSpecWidth == TSW_long) {
|
} else if (TypeSpecWidth == TSW_long) {
|
||||||
// vector long is unsupported for ZVector and deprecated for AltiVec.
|
// vector long is unsupported for ZVector and deprecated for AltiVec.
|
||||||
if (S.getLangOpts().ZVector)
|
if (S.getLangOpts().ZVector)
|
||||||
S.Diag(TSWLoc, diag::err_invalid_vector_long_decl_spec);
|
S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_long_decl_spec);
|
||||||
else
|
else
|
||||||
S.Diag(TSWLoc, diag::warn_vector_long_decl_spec_combination)
|
S.Diag(TSWRange.getBegin(),
|
||||||
<< getSpecifierName((TST)TypeSpecType, Policy);
|
diag::warn_vector_long_decl_spec_combination)
|
||||||
|
<< getSpecifierName((TST)TypeSpecType, Policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TypeAltiVecPixel) {
|
if (TypeAltiVecPixel) {
|
||||||
|
@ -1106,8 +1110,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
|
||||||
if (TypeSpecType == TST_unspecified)
|
if (TypeSpecType == TST_unspecified)
|
||||||
TypeSpecType = TST_int; // short -> short int, long long -> long long int.
|
TypeSpecType = TST_int; // short -> short int, long long -> long long int.
|
||||||
else if (TypeSpecType != TST_int) {
|
else if (TypeSpecType != TST_int) {
|
||||||
S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth
|
S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
|
||||||
<< getSpecifierName((TST)TypeSpecType, Policy);
|
<< (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
|
||||||
TypeSpecType = TST_int;
|
TypeSpecType = TST_int;
|
||||||
TypeSpecOwned = false;
|
TypeSpecOwned = false;
|
||||||
}
|
}
|
||||||
|
@ -1116,8 +1120,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
|
||||||
if (TypeSpecType == TST_unspecified)
|
if (TypeSpecType == TST_unspecified)
|
||||||
TypeSpecType = TST_int; // long -> long int.
|
TypeSpecType = TST_int; // long -> long int.
|
||||||
else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
|
else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
|
||||||
S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth
|
S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
|
||||||
<< getSpecifierName((TST)TypeSpecType, Policy);
|
<< (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
|
||||||
TypeSpecType = TST_int;
|
TypeSpecType = TST_int;
|
||||||
TypeSpecOwned = false;
|
TypeSpecOwned = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4907,11 +4907,9 @@ namespace {
|
||||||
TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs();
|
TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs();
|
||||||
// Try to have a meaningful source location.
|
// Try to have a meaningful source location.
|
||||||
if (TL.getWrittenSignSpec() != TSS_unspecified)
|
if (TL.getWrittenSignSpec() != TSS_unspecified)
|
||||||
// Sign spec loc overrides the others (e.g., 'unsigned long').
|
TL.expandBuiltinRange(DS.getTypeSpecSignLoc());
|
||||||
TL.setBuiltinLoc(DS.getTypeSpecSignLoc());
|
if (TL.getWrittenWidthSpec() != TSW_unspecified)
|
||||||
else if (TL.getWrittenWidthSpec() != TSW_unspecified)
|
TL.expandBuiltinRange(DS.getTypeSpecWidthRange());
|
||||||
// Width spec loc overrides type spec loc (e.g., 'short int').
|
|
||||||
TL.setBuiltinLoc(DS.getTypeSpecWidthLoc());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
|
void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
|
||||||
|
|
|
@ -148,6 +148,96 @@ TEST(VarDecl, VMTypeFixedVarDeclRange) {
|
||||||
varDecl(), Lang_C89));
|
varDecl(), Lang_C89));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, IntRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 1, 1, 1);
|
||||||
|
EXPECT_TRUE(Verifier.match("int a;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, LongRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 1, 1, 1);
|
||||||
|
EXPECT_TRUE(Verifier.match("long a;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, LongDoubleRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 1, 1, 6);
|
||||||
|
EXPECT_TRUE(Verifier.match("long double a;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, DoubleLongRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 1, 1, 8);
|
||||||
|
EXPECT_TRUE(Verifier.match("double long a;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, LongIntRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 1, 1, 6);
|
||||||
|
EXPECT_TRUE(Verifier.match("long int a;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, IntLongRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 1, 1, 5);
|
||||||
|
EXPECT_TRUE(Verifier.match("int long a;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, UnsignedIntRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 1, 1, 10);
|
||||||
|
EXPECT_TRUE(Verifier.match("unsigned int a;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, IntUnsignedRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 1, 1, 5);
|
||||||
|
EXPECT_TRUE(Verifier.match("int unsigned a;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, LongLongRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 1, 1, 6);
|
||||||
|
EXPECT_TRUE(Verifier.match("long long a;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, UnsignedLongLongRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 1, 1, 15);
|
||||||
|
EXPECT_TRUE(Verifier.match("unsigned long long a;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, LongUnsignedLongRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 1, 1, 15);
|
||||||
|
EXPECT_TRUE(Verifier.match("long unsigned long a;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, LongLongUnsignedRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 1, 1, 11);
|
||||||
|
EXPECT_TRUE(Verifier.match("long long unsigned a;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, ConstLongLongRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 7, 1, 12);
|
||||||
|
EXPECT_TRUE(Verifier.match("const long long a = 0;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, LongConstLongRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 1, 1, 12);
|
||||||
|
EXPECT_TRUE(Verifier.match("long const long a = 0;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TypeLoc, LongLongConstRange) {
|
||||||
|
RangeVerifier<TypeLoc> Verifier;
|
||||||
|
Verifier.expectRange(1, 1, 1, 6);
|
||||||
|
EXPECT_TRUE(Verifier.match("long long const a = 0;", typeLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(CXXConstructorDecl, NoRetFunTypeLocRange) {
|
TEST(CXXConstructorDecl, NoRetFunTypeLocRange) {
|
||||||
RangeVerifier<CXXConstructorDecl> Verifier;
|
RangeVerifier<CXXConstructorDecl> Verifier;
|
||||||
Verifier.expectRange(1, 11, 1, 13);
|
Verifier.expectRange(1, 11, 1, 13);
|
||||||
|
|
Loading…
Reference in New Issue