From: Abramo Bagnara Date: Thu, 8 Nov 2012 14:44:42 +0000 (+0000) Subject: Fixed converted ConstantArrayTypeLoc range. Added a missing testcase for ConstructorD... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4c5750e0d1c1dfc091689e3daa96ed4ccfa36dca;p=clang Fixed converted ConstantArrayTypeLoc range. Added a missing testcase for ConstructorDecl source range. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167583 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 52ee80f833..3292dce516 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3875,6 +3875,53 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, Res, ArrayType::Normal, 0); } +/// FixInvalidVariablyModifiedTypeLoc +static void +FixInvalidVariablyModifiedTypeLoc(TypeLoc SrcTL, TypeLoc DstTL) { + if (PointerTypeLoc* SrcPTL = dyn_cast(&SrcTL)) { + PointerTypeLoc* DstPTL = cast(&DstTL); + FixInvalidVariablyModifiedTypeLoc(SrcPTL->getPointeeLoc(), + DstPTL->getPointeeLoc()); + DstPTL->setStarLoc(SrcPTL->getStarLoc()); + return; + } + if (ParenTypeLoc* SrcPTL = dyn_cast(&SrcTL)) { + ParenTypeLoc* DstPTL = cast(&DstTL); + FixInvalidVariablyModifiedTypeLoc(SrcPTL->getInnerLoc(), + DstPTL->getInnerLoc()); + DstPTL->setLParenLoc(SrcPTL->getLParenLoc()); + DstPTL->setRParenLoc(SrcPTL->getRParenLoc()); + return; + } + ArrayTypeLoc* SrcATL = cast(&SrcTL); + ArrayTypeLoc* DstATL = cast(&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 @@ -4002,19 +4049,21 @@ Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) { // 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); @@ -4574,7 +4623,8 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, 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) @@ -4621,11 +4671,10 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, (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]; @@ -4644,7 +4693,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, return false; } - if (FixedTy.isNull()) { + if (FixedTInfo == 0) { if (NewVD->isFileVarDecl()) Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope); else @@ -4654,7 +4703,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, } Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size); - NewVD->setType(FixedTy); + NewVD->setTypeSourceInfo(FixedTInfo); } if (Previous.empty() && NewVD->isExternC()) { @@ -9544,12 +9593,15 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, 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); diff --git a/unittests/AST/SourceLocationTest.cpp b/unittests/AST/SourceLocationTest.cpp index c1651bc586..953cb9e42c 100644 --- a/unittests/AST/SourceLocationTest.cpp +++ b/unittests/AST/SourceLocationTest.cpp @@ -29,7 +29,7 @@ using clang::tooling::newFrontendActionFactory; 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. /// @@ -78,6 +78,10 @@ testing::AssertionResult MatchVerifier::match( 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"; @@ -262,5 +266,18 @@ TEST(MemberExpr, ImplicitMemberRange) { memberExpr())); } +TEST(VarDecl, VMTypeFixedVarDeclRange) { + RangeVerifier Verifier; + Verifier.expectRange(1, 1, 1, 23); + EXPECT_TRUE(Verifier.match("int a[(int)(void*)1234];", + varDecl(), Lang_C89)); +} + +TEST(CXXConstructorDecl, NoRetFunTypeLocRange) { + RangeVerifier Verifier; + Verifier.expectRange(1, 11, 1, 13); + EXPECT_TRUE(Verifier.match("class C { C(); };", functionDecl())); +} + } // end namespace ast_matchers } // end namespace clang