struct BuiltinLocInfo {
- SourceLocation BuiltinLoc;
+ SourceRange BuiltinRange;
};
/// \brief Wrapper for source info for builtin types.
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(); }
}
SourceRange getLocalSourceRange() const {
- return SourceRange(getBuiltinLoc(), getBuiltinLoc());
+ return getLocalData()->BuiltinRange;
}
TypeSpecifierSign getWrittenSignSpec() const {
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
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; }
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;
}
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) {
// 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) &&
// 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);
} 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) {
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;
}
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;
}
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) {
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);