Res, ArrayType::Normal, 0);
}
+/// FixInvalidVariablyModifiedTypeLoc
+static void
+FixInvalidVariablyModifiedTypeLoc(TypeLoc SrcTL, TypeLoc DstTL) {
+ if (PointerTypeLoc* SrcPTL = dyn_cast<PointerTypeLoc>(&SrcTL)) {
+ PointerTypeLoc* DstPTL = cast<PointerTypeLoc>(&DstTL);
+ FixInvalidVariablyModifiedTypeLoc(SrcPTL->getPointeeLoc(),
+ DstPTL->getPointeeLoc());
+ DstPTL->setStarLoc(SrcPTL->getStarLoc());
+ return;
+ }
+ if (ParenTypeLoc* SrcPTL = dyn_cast<ParenTypeLoc>(&SrcTL)) {
+ ParenTypeLoc* DstPTL = cast<ParenTypeLoc>(&DstTL);
+ FixInvalidVariablyModifiedTypeLoc(SrcPTL->getInnerLoc(),
+ DstPTL->getInnerLoc());
+ DstPTL->setLParenLoc(SrcPTL->getLParenLoc());
+ DstPTL->setRParenLoc(SrcPTL->getRParenLoc());
+ return;
+ }
+ ArrayTypeLoc* SrcATL = cast<ArrayTypeLoc>(&SrcTL);
+ ArrayTypeLoc* DstATL = cast<ArrayTypeLoc>(&DstTL);
+ TypeLoc SrcElemTL = SrcATL->getElementLoc();
+ TypeLoc DstElemTL = DstATL->getElementLoc();
+ DstElemTL.initializeFullCopy(SrcElemTL);
+ DstATL->setLBracketLoc(SrcATL->getLBracketLoc());
+ DstATL->setSizeExpr(SrcATL->getSizeExpr());
+ DstATL->setRBracketLoc(SrcATL->getRBracketLoc());
+}
+
+/// TryToFixInvalidVariablyModifiedTypeSourceInfo - Helper method to turn
+/// variable array types into constant array types in certain situations
+/// which would otherwise be errors (for GCC compatibility).
+static TypeSourceInfo*
+TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo,
+ ASTContext &Context,
+ bool &SizeIsNegative,
+ llvm::APSInt &Oversized) {
+ QualType FixedTy
+ = TryToFixInvalidVariablyModifiedType(TInfo->getType(), Context,
+ SizeIsNegative, Oversized);
+ if (FixedTy.isNull())
+ return 0;
+ TypeSourceInfo *FixedTInfo = Context.getTrivialTypeSourceInfo(FixedTy);
+ FixInvalidVariablyModifiedTypeLoc(TInfo->getTypeLoc(),
+ FixedTInfo->getTypeLoc());
+ return FixedTInfo;
+}
+
/// \brief Register the given locally-scoped external C declaration so
/// that it can be found later for redeclarations
void
// then it shall have block scope.
// Note that variably modified types must be fixed before merging the decl so
// that redeclarations will match.
- QualType T = NewTD->getUnderlyingType();
+ TypeSourceInfo *TInfo = NewTD->getTypeSourceInfo();
+ QualType T = TInfo->getType();
if (T->isVariablyModifiedType()) {
getCurFunction()->setHasBranchProtectedScope();
if (S->getFnParent() == 0) {
bool SizeIsNegative;
llvm::APSInt Oversized;
- QualType FixedTy =
- TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative,
- Oversized);
- if (!FixedTy.isNull()) {
+ TypeSourceInfo *FixedTInfo =
+ TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context,
+ SizeIsNegative,
+ Oversized);
+ if (FixedTInfo) {
Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size);
- NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy));
+ NewTD->setTypeSourceInfo(FixedTInfo);
} else {
if (SizeIsNegative)
Diag(NewTD->getLocation(), diag::err_typecheck_negative_array_size);
if (NewVD->isInvalidDecl())
return false;
- QualType T = NewVD->getType();
+ TypeSourceInfo *TInfo = NewVD->getTypeSourceInfo();
+ QualType T = TInfo->getType();
if (T->isObjCObjectType()) {
Diag(NewVD->getLocation(), diag::err_statically_allocated_object)
(T->isVariableArrayType() && NewVD->hasGlobalStorage())) {
bool SizeIsNegative;
llvm::APSInt Oversized;
- QualType FixedTy =
- TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative,
- Oversized);
-
- if (FixedTy.isNull() && T->isVariableArrayType()) {
+ TypeSourceInfo *FixedTInfo =
+ TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context,
+ SizeIsNegative, Oversized);
+ if (FixedTInfo == 0 && T->isVariableArrayType()) {
const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
// FIXME: This won't give the correct result for
// int a[10][n];
return false;
}
- if (FixedTy.isNull()) {
+ if (FixedTInfo == 0) {
if (NewVD->isFileVarDecl())
Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope);
else
}
Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
- NewVD->setType(FixedTy);
+ NewVD->setTypeSourceInfo(FixedTInfo);
}
if (Previous.empty() && NewVD->isExternC()) {
if (!InvalidDecl && T->isVariablyModifiedType()) {
bool SizeIsNegative;
llvm::APSInt Oversized;
- QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context,
- SizeIsNegative,
- Oversized);
- if (!FixedTy.isNull()) {
+
+ TypeSourceInfo *FixedTInfo =
+ TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context,
+ SizeIsNegative,
+ Oversized);
+ if (FixedTInfo) {
Diag(Loc, diag::warn_illegal_constant_array_size);
- T = FixedTy;
+ TInfo = FixedTInfo;
+ T = FixedTInfo->getType();
} else {
if (SizeIsNegative)
Diag(Loc, diag::err_typecheck_negative_array_size);
using clang::tooling::runToolOnCodeWithArgs;
using clang::tooling::FrontendActionFactory;
-enum Language { Lang_C, Lang_CXX };
+enum Language { Lang_C, Lang_C89, Lang_CXX };
/// \brief Base class for verifying some property of nodes found by a matcher.
///
Args.push_back("-std=c99");
FileName = "input.c";
break;
+ case Lang_C89:
+ Args.push_back("-std=c89");
+ FileName = "input.c";
+ break;
case Lang_CXX:
Args.push_back("-std=c++98");
FileName = "input.cc";
memberExpr()));
}
+TEST(VarDecl, VMTypeFixedVarDeclRange) {
+ RangeVerifier<VarDecl> Verifier;
+ Verifier.expectRange(1, 1, 1, 23);
+ EXPECT_TRUE(Verifier.match("int a[(int)(void*)1234];",
+ varDecl(), Lang_C89));
+}
+
+TEST(CXXConstructorDecl, NoRetFunTypeLocRange) {
+ RangeVerifier<CXXConstructorDecl> Verifier;
+ Verifier.expectRange(1, 11, 1, 13);
+ EXPECT_TRUE(Verifier.match("class C { C(); };", functionDecl()));
+}
+
} // end namespace ast_matchers
} // end namespace clang