Author: malcolm.parsons Date: Fri Oct 21 16:13:56 2016 New Revision: 284885
URL: http://llvm.org/viewvc/llvm-project?rev=284885&view=rev Log: [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 Modified: cfe/trunk/include/clang/AST/TypeLoc.h cfe/trunk/include/clang/Sema/DeclSpec.h cfe/trunk/lib/Sema/DeclSpec.cpp cfe/trunk/lib/Sema/SemaType.cpp cfe/trunk/unittests/AST/SourceLocationTest.cpp Modified: cfe/trunk/include/clang/AST/TypeLoc.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=284885&r1=284884&r2=284885&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/TypeLoc.h (original) +++ cfe/trunk/include/clang/AST/TypeLoc.h Fri Oct 21 16:13:56 2016 @@ -512,7 +512,7 @@ private: struct BuiltinLocInfo { - SourceLocation BuiltinLoc; + SourceRange BuiltinRange; }; /// \brief Wrapper for source info for builtin types. @@ -522,10 +522,19 @@ class BuiltinTypeLoc : public ConcreteTy BuiltinLocInfo> { public: SourceLocation getBuiltinLoc() const { - return getLocalData()->BuiltinLoc; + return getLocalData()->BuiltinRange.getBegin(); } 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(); } @@ -554,7 +563,7 @@ public: } SourceRange getLocalSourceRange() const { - return SourceRange(getBuiltinLoc(), getBuiltinLoc()); + return getLocalData()->BuiltinRange; } TypeSpecifierSign getWrittenSignSpec() const { Modified: cfe/trunk/include/clang/Sema/DeclSpec.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=284885&r1=284884&r2=284885&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/DeclSpec.h (original) +++ cfe/trunk/include/clang/Sema/DeclSpec.h Fri Oct 21 16:13:56 2016 @@ -380,7 +380,8 @@ private: SourceRange Range; 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, /// typename, then this is the location of the named type (if present); /// 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 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 getTypeSpecSignLoc() const { return TSSLoc; } SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; } Modified: cfe/trunk/lib/Sema/DeclSpec.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=284885&r1=284884&r2=284885&view=diff ============================================================================== --- cfe/trunk/lib/Sema/DeclSpec.cpp (original) +++ cfe/trunk/lib/Sema/DeclSpec.cpp Fri Oct 21 16:13:56 2016 @@ -610,14 +610,16 @@ bool DeclSpec::SetTypeSpecWidth(TSW W, S const char *&PrevSpec, unsigned &DiagID, 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'. if (TypeSpecWidth == TSW_unspecified) - TSWLoc = Loc; + TSWRange.setBegin(Loc); // Allow turning long -> long long. else if (W != TSW_longlong || TypeSpecWidth != TSW_long) return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID); TypeSpecWidth = W; + // Remember location of the last 'long' + TSWRange.setEnd(Loc); return false; } @@ -997,9 +999,9 @@ void DeclSpec::Finish(Sema &S, const Pri TypeQualifiers)) { const unsigned NumLocs = 9; SourceLocation ExtraLocs[NumLocs] = { - TSWLoc, TSCLoc, TSSLoc, AltiVecLoc, - TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc, TQ_unalignedLoc - }; + TSWRange.getBegin(), TSCLoc, TSSLoc, + AltiVecLoc, TQ_constLoc, TQ_restrictLoc, + TQ_volatileLoc, TQ_atomicLoc, TQ_unalignedLoc}; FixItHint Hints[NumLocs]; SourceLocation FirstLoc; for (unsigned I = 0; I != NumLocs; ++I) { @@ -1041,8 +1043,8 @@ void DeclSpec::Finish(Sema &S, const Pri // Only 'short' and 'long long' are valid with vector bool. (PIM 2.1) if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short) && (TypeSpecWidth != TSW_longlong)) - S.Diag(TSWLoc, diag::err_invalid_vector_bool_decl_spec) - << getSpecifierName((TSW)TypeSpecWidth); + S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_bool_decl_spec) + << getSpecifierName((TSW)TypeSpecWidth); // vector bool long long requires VSX support or ZVector. if ((TypeSpecWidth == TSW_longlong) && @@ -1059,7 +1061,8 @@ void DeclSpec::Finish(Sema &S, const Pri // vector long double and vector long long double are never allowed. // vector double is OK for Power7 and later, and ZVector. 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") && !S.getLangOpts().ZVector) S.Diag(TSTLoc, diag::err_invalid_vector_double_decl_spec); @@ -1070,10 +1073,11 @@ void DeclSpec::Finish(Sema &S, const Pri } else if (TypeSpecWidth == TSW_long) { // vector long is unsupported for ZVector and deprecated for AltiVec. 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 - S.Diag(TSWLoc, diag::warn_vector_long_decl_spec_combination) - << getSpecifierName((TST)TypeSpecType, Policy); + S.Diag(TSWRange.getBegin(), + diag::warn_vector_long_decl_spec_combination) + << getSpecifierName((TST)TypeSpecType, Policy); } if (TypeAltiVecPixel) { @@ -1106,8 +1110,8 @@ void DeclSpec::Finish(Sema &S, const Pri if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // short -> short int, long long -> long long int. else if (TypeSpecType != TST_int) { - S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth - << getSpecifierName((TST)TypeSpecType, Policy); + S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec) + << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecType = TST_int; TypeSpecOwned = false; } @@ -1116,8 +1120,8 @@ void DeclSpec::Finish(Sema &S, const Pri if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // long -> long int. else if (TypeSpecType != TST_int && TypeSpecType != TST_double) { - S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth - << getSpecifierName((TST)TypeSpecType, Policy); + S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec) + << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecType = TST_int; TypeSpecOwned = false; } Modified: cfe/trunk/lib/Sema/SemaType.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=284885&r1=284884&r2=284885&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaType.cpp (original) +++ cfe/trunk/lib/Sema/SemaType.cpp Fri Oct 21 16:13:56 2016 @@ -4907,11 +4907,9 @@ namespace { TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs(); // Try to have a meaningful source location. if (TL.getWrittenSignSpec() != TSS_unspecified) - // Sign spec loc overrides the others (e.g., 'unsigned long'). - TL.setBuiltinLoc(DS.getTypeSpecSignLoc()); - else if (TL.getWrittenWidthSpec() != TSW_unspecified) - // Width spec loc overrides type spec loc (e.g., 'short int'). - TL.setBuiltinLoc(DS.getTypeSpecWidthLoc()); + TL.expandBuiltinRange(DS.getTypeSpecSignLoc()); + if (TL.getWrittenWidthSpec() != TSW_unspecified) + TL.expandBuiltinRange(DS.getTypeSpecWidthRange()); } } void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { Modified: cfe/trunk/unittests/AST/SourceLocationTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/SourceLocationTest.cpp?rev=284885&r1=284884&r2=284885&view=diff ============================================================================== --- cfe/trunk/unittests/AST/SourceLocationTest.cpp (original) +++ cfe/trunk/unittests/AST/SourceLocationTest.cpp Fri Oct 21 16:13:56 2016 @@ -148,6 +148,96 @@ TEST(VarDecl, VMTypeFixedVarDeclRange) { 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) { RangeVerifier<CXXConstructorDecl> Verifier; Verifier.expectRange(1, 11, 1, 13); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits