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
This commit is contained in:
Eli Friedman 2013-08-15 22:02:56 +00:00
parent 35b22f6985
commit 89fe0d5842
10 changed files with 46 additions and 25 deletions

View File

@ -1206,17 +1206,16 @@ public:
/// x = int(0.5); /// x = int(0.5);
/// \endcode /// \endcode
class CXXFunctionalCastExpr : public ExplicitCastExpr { class CXXFunctionalCastExpr : public ExplicitCastExpr {
SourceLocation TyBeginLoc; SourceLocation LParenLoc;
SourceLocation RParenLoc; SourceLocation RParenLoc;
CXXFunctionalCastExpr(QualType ty, ExprValueKind VK, CXXFunctionalCastExpr(QualType ty, ExprValueKind VK,
TypeSourceInfo *writtenTy, TypeSourceInfo *writtenTy,
SourceLocation tyBeginLoc, CastKind kind, CastKind kind, Expr *castExpr, unsigned pathSize,
Expr *castExpr, unsigned pathSize, SourceLocation lParenLoc, SourceLocation rParenLoc)
SourceLocation rParenLoc)
: ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind, : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind,
castExpr, pathSize, writtenTy), castExpr, pathSize, writtenTy),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} LParenLoc(lParenLoc), RParenLoc(rParenLoc) {}
explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize) explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
: ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { } : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { }
@ -1225,22 +1224,20 @@ public:
static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T, static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T,
ExprValueKind VK, ExprValueKind VK,
TypeSourceInfo *Written, TypeSourceInfo *Written,
SourceLocation TyBeginLoc,
CastKind Kind, Expr *Op, CastKind Kind, Expr *Op,
const CXXCastPath *Path, const CXXCastPath *Path,
SourceLocation LPLoc,
SourceLocation RPLoc); SourceLocation RPLoc);
static CXXFunctionalCastExpr *CreateEmpty(ASTContext &Context, static CXXFunctionalCastExpr *CreateEmpty(ASTContext &Context,
unsigned PathSize); unsigned PathSize);
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } SourceLocation getLParenLoc() const { return LParenLoc; }
void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; } void setLParenLoc(SourceLocation L) { LParenLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; } void setRParenLoc(SourceLocation L) { RParenLoc = L; }
SourceLocation getLocStart() const LLVM_READONLY { return TyBeginLoc; } SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY { SourceLocation getLocEnd() const LLVM_READONLY;
return RParenLoc.isValid() ? RParenLoc : getSubExpr()->getLocEnd();
}
static bool classof(const Stmt *T) { static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXFunctionalCastExprClass; return T->getStmtClass() == CXXFunctionalCastExprClass;

View File

@ -2177,7 +2177,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
WarnE = this; WarnE = this;
if (const CXXFunctionalCastExpr *CXXCE = if (const CXXFunctionalCastExpr *CXXCE =
dyn_cast<CXXFunctionalCastExpr>(this)) { dyn_cast<CXXFunctionalCastExpr>(this)) {
Loc = CXXCE->getTypeBeginLoc(); Loc = CXXCE->getLocStart();
R1 = CXXCE->getSubExpr()->getSourceRange(); R1 = CXXCE->getSubExpr()->getSourceRange();
} else { } else {
const CStyleCastExpr *CStyleCE = cast<CStyleCastExpr>(this); const CStyleCastExpr *CStyleCE = cast<CStyleCastExpr>(this);

View File

@ -660,14 +660,14 @@ CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(ASTContext &C) {
CXXFunctionalCastExpr * CXXFunctionalCastExpr *
CXXFunctionalCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK, CXXFunctionalCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK,
TypeSourceInfo *Written, SourceLocation L, TypeSourceInfo *Written, CastKind K, Expr *Op,
CastKind K, Expr *Op, const CXXCastPath *BasePath, const CXXCastPath *BasePath,
SourceLocation R) { SourceLocation L, SourceLocation R) {
unsigned PathSize = (BasePath ? BasePath->size() : 0); unsigned PathSize = (BasePath ? BasePath->size() : 0);
void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr) void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr)
+ PathSize * sizeof(CXXBaseSpecifier*)); + PathSize * sizeof(CXXBaseSpecifier*));
CXXFunctionalCastExpr *E = 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); if (PathSize) E->setCastPath(*BasePath);
return E; return E;
} }
@ -679,6 +679,14 @@ CXXFunctionalCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), 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::LiteralOperatorKind
UserDefinedLiteral::getLiteralOperatorKind() const { UserDefinedLiteral::getLiteralOperatorKind() const {
if (getNumArgs() == 0) if (getNumArgs() == 0)

View File

@ -227,7 +227,7 @@ static SourceLocation GetUnreachableLoc(const Stmt *S,
case Expr::CXXFunctionalCastExprClass: { case Expr::CXXFunctionalCastExprClass: {
const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S); const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S);
R1 = CE->getSubExpr()->getSourceRange(); R1 = CE->getSubExpr()->getSourceRange();
return CE->getTypeBeginLoc(); return CE->getLocStart();
} }
case Stmt::CXXTryStmtClass: { case Stmt::CXXTryStmtClass: {
return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc(); return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();

View File

@ -2364,6 +2364,6 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
ConstructExpr->setParenRange(SourceRange(LPLoc, RPLoc)); ConstructExpr->setParenRange(SourceRange(LPLoc, RPLoc));
return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType, return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType,
Op.ValueKind, CastTypeInfo, Op.DestRange.getBegin(), Op.ValueKind, CastTypeInfo, Op.Kind,
Op.Kind, Op.SrcExpr.take(), &Op.BasePath, RPLoc)); Op.SrcExpr.take(), &Op.BasePath, LPLoc, RPLoc));
} }

View File

@ -902,8 +902,9 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
InitListExpr *List = cast<InitListExpr>(Result.take()); InitListExpr *List = cast<InitListExpr>(Result.take());
Result = Owned(CXXFunctionalCastExpr::Create(Context, List->getType(), Result = Owned(CXXFunctionalCastExpr::Create(Context, List->getType(),
Expr::getValueKindForType(TInfo->getType()), Expr::getValueKindForType(TInfo->getType()),
TInfo, TyBeginLoc, CK_NoOp, TInfo, CK_NoOp, List,
List, /*Path=*/0, RParenLoc)); /*Path=*/0,
LParenLoc, RParenLoc));
} }
// FIXME: Improve AST representation? // FIXME: Improve AST representation?

View File

@ -7317,7 +7317,7 @@ TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
return SemaRef.Owned(E); return SemaRef.Owned(E);
return getDerived().RebuildCXXFunctionalCastExpr(Type, return getDerived().RebuildCXXFunctionalCastExpr(Type,
/*FIXME:*/E->getSubExpr()->getLocStart(), E->getLParenLoc(),
SubExpr.get(), SubExpr.get(),
E->getRParenLoc()); E->getRParenLoc());
} }

View File

@ -1263,7 +1263,7 @@ void ASTStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
void ASTStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { void ASTStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
VisitExplicitCastExpr(E); VisitExplicitCastExpr(E);
E->setTypeBeginLoc(ReadSourceLocation(Record, Idx)); E->setLParenLoc(ReadSourceLocation(Record, Idx));
E->setRParenLoc(ReadSourceLocation(Record, Idx)); E->setRParenLoc(ReadSourceLocation(Record, Idx));
} }

View File

@ -1226,7 +1226,7 @@ void ASTStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
void ASTStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { void ASTStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
VisitExplicitCastExpr(E); VisitExplicitCastExpr(E);
Writer.AddSourceLocation(E->getTypeBeginLoc(), Record); Writer.AddSourceLocation(E->getLParenLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record); Writer.AddSourceLocation(E->getRParenLoc(), Record);
Code = serialization::EXPR_CXX_FUNCTIONAL_CAST; Code = serialization::EXPR_CXX_FUNCTIONAL_CAST;
} }

View File

@ -118,3 +118,18 @@ namespace PR13064 {
template<typename T> struct C { T a = { 0 }; }; // expected-error{{explicit}} template<typename T> struct C { T a = { 0 }; }; // expected-error{{explicit}}
C<A> c; // expected-note{{here}} C<A> c; // expected-note{{here}}
} }
namespace PR16903 {
// Make sure we properly instantiate list-initialization.
template<typename T>
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);
}
}