From 89fe0d5842469f231c2a0649ff6d88ade892e6e8 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 15 Aug 2013 22:02:56 +0000 Subject: [PATCH] Properly track l-paren of a CXXFucntionalCastExpr. In addition to storing more useful information in the AST, this fixes a semantic check in template instantiation which checks whether the l-paren location is valid. Fixes PR16903. llvm-svn: 188495 --- clang/include/clang/AST/ExprCXX.h | 21 +++++++++----------- clang/lib/AST/Expr.cpp | 2 +- clang/lib/AST/ExprCXX.cpp | 16 +++++++++++---- clang/lib/Analysis/ReachableCode.cpp | 2 +- clang/lib/Sema/SemaCast.cpp | 4 ++-- clang/lib/Sema/SemaExprCXX.cpp | 5 +++-- clang/lib/Sema/TreeTransform.h | 2 +- clang/lib/Serialization/ASTReaderStmt.cpp | 2 +- clang/lib/Serialization/ASTWriterStmt.cpp | 2 +- clang/test/SemaTemplate/instantiate-init.cpp | 15 ++++++++++++++ 10 files changed, 46 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 4a6cfae0681f..cf3b88bd2a9d 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -1206,17 +1206,16 @@ public: /// x = int(0.5); /// \endcode class CXXFunctionalCastExpr : public ExplicitCastExpr { - SourceLocation TyBeginLoc; + SourceLocation LParenLoc; SourceLocation RParenLoc; CXXFunctionalCastExpr(QualType ty, ExprValueKind VK, TypeSourceInfo *writtenTy, - SourceLocation tyBeginLoc, CastKind kind, - Expr *castExpr, unsigned pathSize, - SourceLocation rParenLoc) + CastKind kind, Expr *castExpr, unsigned pathSize, + SourceLocation lParenLoc, SourceLocation rParenLoc) : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind, castExpr, pathSize, writtenTy), - TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} + LParenLoc(lParenLoc), RParenLoc(rParenLoc) {} explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize) : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { } @@ -1225,22 +1224,20 @@ public: static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T, ExprValueKind VK, TypeSourceInfo *Written, - SourceLocation TyBeginLoc, CastKind Kind, Expr *Op, const CXXCastPath *Path, + SourceLocation LPLoc, SourceLocation RPLoc); static CXXFunctionalCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize); - SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } - void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; } + SourceLocation getLParenLoc() const { return LParenLoc; } + void setLParenLoc(SourceLocation L) { LParenLoc = L; } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceLocation getLocStart() const LLVM_READONLY { return TyBeginLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return RParenLoc.isValid() ? RParenLoc : getSubExpr()->getLocEnd(); - } + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXFunctionalCastExprClass; diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 5c1a27da3658..3eeb53e62016 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -2177,7 +2177,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, WarnE = this; if (const CXXFunctionalCastExpr *CXXCE = dyn_cast(this)) { - Loc = CXXCE->getTypeBeginLoc(); + Loc = CXXCE->getLocStart(); R1 = CXXCE->getSubExpr()->getSourceRange(); } else { const CStyleCastExpr *CStyleCE = cast(this); diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 055fc3b8142b..0609eb1d65d6 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -660,14 +660,14 @@ CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(ASTContext &C) { CXXFunctionalCastExpr * CXXFunctionalCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK, - TypeSourceInfo *Written, SourceLocation L, - CastKind K, Expr *Op, const CXXCastPath *BasePath, - SourceLocation R) { + TypeSourceInfo *Written, CastKind K, Expr *Op, + const CXXCastPath *BasePath, + SourceLocation L, SourceLocation R) { unsigned PathSize = (BasePath ? BasePath->size() : 0); void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); CXXFunctionalCastExpr *E = - new (Buffer) CXXFunctionalCastExpr(T, VK, Written, L, K, Op, PathSize, R); + new (Buffer) CXXFunctionalCastExpr(T, VK, Written, K, Op, PathSize, L, R); if (PathSize) E->setCastPath(*BasePath); return E; } @@ -679,6 +679,14 @@ CXXFunctionalCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) { return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize); } +SourceLocation CXXFunctionalCastExpr::getLocStart() const { + return getTypeInfoAsWritten()->getTypeLoc().getLocStart(); +} + +SourceLocation CXXFunctionalCastExpr::getLocEnd() const { + return RParenLoc.isValid() ? RParenLoc : getSubExpr()->getLocEnd(); +} + UserDefinedLiteral::LiteralOperatorKind UserDefinedLiteral::getLiteralOperatorKind() const { if (getNumArgs() == 0) diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp index a90aebbe28ed..e15fe7d12663 100644 --- a/clang/lib/Analysis/ReachableCode.cpp +++ b/clang/lib/Analysis/ReachableCode.cpp @@ -227,7 +227,7 @@ static SourceLocation GetUnreachableLoc(const Stmt *S, case Expr::CXXFunctionalCastExprClass: { const CXXFunctionalCastExpr *CE = cast (S); R1 = CE->getSubExpr()->getSourceRange(); - return CE->getTypeBeginLoc(); + return CE->getLocStart(); } case Stmt::CXXTryStmtClass: { return cast(S)->getHandler(0)->getCatchLoc(); diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 888c14ec3924..e3227bcaefe9 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -2364,6 +2364,6 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, ConstructExpr->setParenRange(SourceRange(LPLoc, RPLoc)); return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType, - Op.ValueKind, CastTypeInfo, Op.DestRange.getBegin(), - Op.Kind, Op.SrcExpr.take(), &Op.BasePath, RPLoc)); + Op.ValueKind, CastTypeInfo, Op.Kind, + Op.SrcExpr.take(), &Op.BasePath, LPLoc, RPLoc)); } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index ee2eb6d02f6a..0b58a3d86d8a 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -902,8 +902,9 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, InitListExpr *List = cast(Result.take()); Result = Owned(CXXFunctionalCastExpr::Create(Context, List->getType(), Expr::getValueKindForType(TInfo->getType()), - TInfo, TyBeginLoc, CK_NoOp, - List, /*Path=*/0, RParenLoc)); + TInfo, CK_NoOp, List, + /*Path=*/0, + LParenLoc, RParenLoc)); } // FIXME: Improve AST representation? diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index b3e8720f5e64..9e5738394eae 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -7317,7 +7317,7 @@ TreeTransform::TransformCXXFunctionalCastExpr( return SemaRef.Owned(E); return getDerived().RebuildCXXFunctionalCastExpr(Type, - /*FIXME:*/E->getSubExpr()->getLocStart(), + E->getLParenLoc(), SubExpr.get(), E->getRParenLoc()); } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index c0193c37726c..eaea0f905cb7 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1263,7 +1263,7 @@ void ASTStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) { void ASTStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { VisitExplicitCastExpr(E); - E->setTypeBeginLoc(ReadSourceLocation(Record, Idx)); + E->setLParenLoc(ReadSourceLocation(Record, Idx)); E->setRParenLoc(ReadSourceLocation(Record, Idx)); } diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 533496d5dc49..95b96766875b 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1226,7 +1226,7 @@ void ASTStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) { void ASTStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { VisitExplicitCastExpr(E); - Writer.AddSourceLocation(E->getTypeBeginLoc(), Record); + Writer.AddSourceLocation(E->getLParenLoc(), Record); Writer.AddSourceLocation(E->getRParenLoc(), Record); Code = serialization::EXPR_CXX_FUNCTIONAL_CAST; } diff --git a/clang/test/SemaTemplate/instantiate-init.cpp b/clang/test/SemaTemplate/instantiate-init.cpp index 6a1a57ca659e..22c70be3a8dc 100644 --- a/clang/test/SemaTemplate/instantiate-init.cpp +++ b/clang/test/SemaTemplate/instantiate-init.cpp @@ -118,3 +118,18 @@ namespace PR13064 { template struct C { T a = { 0 }; }; // expected-error{{explicit}} C c; // expected-note{{here}} } + +namespace PR16903 { + // Make sure we properly instantiate list-initialization. + template + void fun (T it) { + int m = 0; + for (int i = 0; i < 4; ++i, ++it){ + m |= long{char{*it}}; + } + } + int test() { + char in[4] = {0,0,0,0}; + fun(in); + } +} -- 2.34.1