diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 4abea4b3234e..b9ab813a7dc8 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -712,6 +712,7 @@ private: CXXConstructorDecl *Constructor; SourceLocation Loc; + SourceRange ParenRange; bool Elidable : 1; bool ZeroInitialization : 1; unsigned ConstructKind : 2; @@ -724,7 +725,8 @@ protected: CXXConstructorDecl *d, bool elidable, Expr **args, unsigned numargs, bool ZeroInitialization = false, - ConstructionKind ConstructKind = CK_Complete); + ConstructionKind ConstructKind = CK_Complete, + SourceRange ParenRange = SourceRange()); /// \brief Construct an empty C++ construction expression. CXXConstructExpr(StmtClass SC, EmptyShell Empty) @@ -743,7 +745,8 @@ public: CXXConstructorDecl *D, bool Elidable, Expr **Args, unsigned NumArgs, bool ZeroInitialization = false, - ConstructionKind ConstructKind = CK_Complete); + ConstructionKind ConstructKind = CK_Complete, + SourceRange ParenRange = SourceRange()); CXXConstructorDecl* getConstructor() const { return Constructor; } @@ -800,6 +803,7 @@ public: } virtual SourceRange getSourceRange() const; + SourceRange getParenRange() const { return ParenRange; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstructExprClass || @@ -872,20 +876,18 @@ public: /// }; /// @endcode class CXXTemporaryObjectExpr : public CXXConstructExpr { - SourceLocation RParenLoc; TypeSourceInfo *Type; public: CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons, TypeSourceInfo *Type, Expr **Args,unsigned NumArgs, - SourceLocation rParenLoc, + SourceRange parenRange, bool ZeroInitialization = false); explicit CXXTemporaryObjectExpr(EmptyShell Empty) : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { } TypeSourceInfo *getTypeSourceInfo() const { return Type; } - SourceLocation getRParenLoc() const { return RParenLoc; } virtual SourceRange getSourceRange() const; @@ -974,6 +976,8 @@ class CXXNewExpr : public Expr { SourceLocation StartLoc; SourceLocation EndLoc; + SourceLocation ConstructorLParen; + SourceLocation ConstructorRParen; friend class ASTStmtReader; public: @@ -984,7 +988,9 @@ public: Expr **constructorArgs, unsigned numConsArgs, FunctionDecl *operatorDelete, QualType ty, TypeSourceInfo *AllocatedTypeInfo, - SourceLocation startLoc, SourceLocation endLoc); + SourceLocation startLoc, SourceLocation endLoc, + SourceLocation constructorLParen, + SourceLocation constructorRParen); explicit CXXNewExpr(EmptyShell Shell) : Expr(CXXNewExprClass, Shell), SubExprs(0) { } @@ -1080,12 +1086,12 @@ public: const_arg_iterator raw_arg_begin() const { return SubExprs; } const_arg_iterator raw_arg_end() const { return constructor_arg_end(); } - SourceLocation getStartLoc() const { return StartLoc; } - void setStartLoc(SourceLocation L) { StartLoc = L; } SourceLocation getEndLoc() const { return EndLoc; } - void setEndLoc(SourceLocation L) { EndLoc = L; } - + + SourceLocation getConstructorLParen() const { return ConstructorLParen; } + SourceLocation getConstructorRParen() const { return ConstructorRParen; } + virtual SourceRange getSourceRange() const { return SourceRange(StartLoc, EndLoc); } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 5e790e2da63c..c4d9c0e2c66e 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2065,7 +2065,8 @@ public: ExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, MultiExprArg Exprs, - bool RequiresZeroInit, unsigned ConstructKind); + bool RequiresZeroInit, unsigned ConstructKind, + SourceRange ParenRange); // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if // the constructor can be elidable? @@ -2073,7 +2074,8 @@ public: BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs, bool RequiresZeroInit, - unsigned ConstructKind); + unsigned ConstructKind, + SourceRange ParenRange); /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating /// the default expr if needed. diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 49e7f99e0de1..0cdf8dd075d6 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -113,14 +113,16 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, Expr **constructorArgs, unsigned numConsArgs, FunctionDecl *operatorDelete, QualType ty, TypeSourceInfo *AllocatedTypeInfo, - SourceLocation startLoc, SourceLocation endLoc) + SourceLocation startLoc, SourceLocation endLoc, + SourceLocation constructorLParen, + SourceLocation constructorRParen) : Expr(CXXNewExprClass, ty, ty->isDependentType(), ty->isDependentType()), GlobalNew(globalNew), Initializer(initializer), SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete), Constructor(constructor), AllocatedTypeInfo(AllocatedTypeInfo), TypeIdParens(TypeIdParens), - StartLoc(startLoc), EndLoc(endLoc) { - + StartLoc(startLoc), EndLoc(endLoc), ConstructorLParen(constructorLParen), + ConstructorRParen(constructorRParen) { AllocateArgsArray(C, arraySize != 0, numPlaceArgs, numConsArgs); unsigned i = 0; if (Array) @@ -344,16 +346,10 @@ StmtIterator DependentScopeDeclRefExpr::child_end() { return child_iterator(); } -SourceRange CXXConstructExpr::getSourceRange() const { - // FIXME: Should we know where the parentheses are, if there are any? - for (std::reverse_iterator I(&Args[NumArgs]), E(&Args[0]); I!=E;++I) { - // Ignore CXXDefaultExprs when computing the range, as they don't - // have a range. - if (!isa(*I)) - return SourceRange(Loc, (*I)->getLocEnd()); - } - - return SourceRange(Loc); +SourceRange CXXConstructExpr::getSourceRange() const { + return ParenRange.isValid() ? + SourceRange(Loc, ParenRange.getEnd()) : + SourceRange(Loc); } SourceRange CXXOperatorCallExpr::getSourceRange() const { @@ -535,17 +531,19 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C, TypeSourceInfo *Type, Expr **Args, unsigned NumArgs, - SourceLocation rParenLoc, + SourceRange parenRange, bool ZeroInitialization) : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type->getType().getNonReferenceType(), Type->getTypeLoc().getBeginLoc(), - Cons, false, Args, NumArgs, ZeroInitialization), - RParenLoc(rParenLoc), Type(Type) { + Cons, false, Args, NumArgs, ZeroInitialization, + CXXConstructExpr::CK_Complete, parenRange), + Type(Type) { } SourceRange CXXTemporaryObjectExpr::getSourceRange() const { - return SourceRange(Type->getTypeLoc().getBeginLoc(), RParenLoc); + return SourceRange(Type->getTypeLoc().getBeginLoc(), + getParenRange().getEnd()); } CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T, @@ -553,10 +551,11 @@ CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T, CXXConstructorDecl *D, bool Elidable, Expr **Args, unsigned NumArgs, bool ZeroInitialization, - ConstructionKind ConstructKind) { + ConstructionKind ConstructKind, + SourceRange ParenRange) { return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D, Elidable, Args, NumArgs, ZeroInitialization, - ConstructKind); + ConstructKind, ParenRange); } CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, @@ -564,12 +563,13 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, CXXConstructorDecl *D, bool elidable, Expr **args, unsigned numargs, bool ZeroInitialization, - ConstructionKind ConstructKind) + ConstructionKind ConstructKind, + SourceRange ParenRange) : Expr(SC, T, T->isDependentType(), (T->isDependentType() || CallExpr::hasAnyValueDependentArguments(args, numargs))), - Constructor(D), Loc(Loc), Elidable(elidable), + Constructor(D), Loc(Loc), ParenRange(ParenRange), Elidable(elidable), ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind), Args(0), NumArgs(numargs) { diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 564dab49de83..fcd0dcdfeaca 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5365,7 +5365,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, MultiExprArg ExprArgs, bool RequiresZeroInit, - unsigned ConstructKind) { + unsigned ConstructKind, + SourceRange ParenRange) { bool Elidable = false; // C++0x [class.copy]p34: @@ -5386,7 +5387,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, Elidable, move(ExprArgs), RequiresZeroInit, - ConstructKind); + ConstructKind, ParenRange); } /// BuildCXXConstructExpr - Creates a complete call to a constructor, @@ -5396,7 +5397,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg ExprArgs, bool RequiresZeroInit, - unsigned ConstructKind) { + unsigned ConstructKind, + SourceRange ParenRange) { unsigned NumExprs = ExprArgs.size(); Expr **Exprs = (Expr **)ExprArgs.release(); @@ -5404,15 +5406,18 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, Constructor, Elidable, Exprs, NumExprs, RequiresZeroInit, - static_cast(ConstructKind))); + static_cast(ConstructKind), + ParenRange)); } bool Sema::InitializeVarWithConstructor(VarDecl *VD, CXXConstructorDecl *Constructor, MultiExprArg Exprs) { + // FIXME: Provide the correct paren SourceRange when available. ExprResult TempResult = BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor, - move(Exprs), false, CXXConstructExpr::CK_Complete); + move(Exprs), false, CXXConstructExpr::CK_Complete, + SourceRange()); if (TempResult.isInvalid()) return true; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 38634794767f..66470904ca34 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -911,7 +911,8 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, ResultType, AllocTypeInfo, StartLoc, Init ? ConstructorRParen : - TypeRange.getEnd())); + TypeRange.getEnd(), + ConstructorLParen, ConstructorRParen)); } /// CheckAllocatedType - Checks that a type is suitable as the allocated type @@ -1668,7 +1669,8 @@ static ExprResult BuildCXXCastArgument(Sema &S, ExprResult Result = S.BuildCXXConstructExpr(CastLoc, Ty, cast(Method), move_arg(ConstructorArgs), - /*ZeroInit*/ false, CXXConstructExpr::CK_Complete); + /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, + SourceRange()); if (Result.isInvalid()) return ExprError(); @@ -1801,7 +1803,8 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, ToType, SCS.CopyConstructor, move_arg(ConstructorArgs), /*ZeroInit*/ false, - CXXConstructExpr::CK_Complete); + CXXConstructExpr::CK_Complete, + SourceRange()); if (FromResult.isInvalid()) return true; From = FromResult.takeAs(); @@ -1812,7 +1815,8 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, ToType, SCS.CopyConstructor, MultiExprArg(*this, &From, 1), /*ZeroInit*/ false, - CXXConstructExpr::CK_Complete); + CXXConstructExpr::CK_Complete, + SourceRange()); if (FromResult.isInvalid()) return true; diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 1e48930f9723..fb482bf56a17 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3444,7 +3444,8 @@ static ExprResult CopyObject(Sema &S, CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable, move_arg(ConstructorArgs), /*ZeroInit*/ false, - CXXConstructExpr::CK_Complete); + CXXConstructExpr::CK_Complete, + SourceRange()); // If we're supposed to bind temporaries, do so. if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity)) @@ -3707,7 +3708,8 @@ InitializationSequence::Perform(Sema &S, CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, move_arg(ConstructorArgs), /*ZeroInit*/ false, - CXXConstructExpr::CK_Complete); + CXXConstructExpr::CK_Complete, + SourceRange()); if (CurInit.isInvalid()) return ExprError(); @@ -3870,7 +3872,7 @@ InitializationSequence::Perform(Sema &S, TSInfo, Exprs, NumExprs, - Kind.getParenRange().getEnd(), + Kind.getParenRange(), ConstructorInitRequiresZeroInit)); } else { CXXConstructExpr::ConstructionKind ConstructKind = @@ -3882,6 +3884,11 @@ InitializationSequence::Perform(Sema &S, CXXConstructExpr::CK_NonVirtualBase; } + // Only get the parenthesis range if it is a direct construction. + SourceRange parenRange = + Kind.getKind() == InitializationKind::IK_Direct ? + Kind.getParenRange() : SourceRange(); + // If the entity allows NRVO, mark the construction as elidable // unconditionally. if (Entity.allowsNRVO()) @@ -3889,13 +3896,15 @@ InitializationSequence::Perform(Sema &S, Constructor, /*Elidable=*/true, move_arg(ConstructorArgs), ConstructorInitRequiresZeroInit, - ConstructKind); + ConstructKind, + parenRange); else CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), Constructor, move_arg(ConstructorArgs), ConstructorInitRequiresZeroInit, - ConstructKind); + ConstructKind, + parenRange); } if (CurInit.isInvalid()) return ExprError(); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 0a57c3536f6c..9dd6bd3456ec 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1688,7 +1688,8 @@ public: bool IsElidable, MultiExprArg Args, bool RequiresZeroInit, - CXXConstructExpr::ConstructionKind ConstructKind) { + CXXConstructExpr::ConstructionKind ConstructKind, + SourceRange ParenRange) { ASTOwningVector ConvertedArgs(SemaRef); if (getSema().CompleteConstructorCall(Constructor, move(Args), Loc, ConvertedArgs)) @@ -1696,7 +1697,8 @@ public: return getSema().BuildCXXConstructExpr(Loc, T, Constructor, IsElidable, move_arg(ConvertedArgs), - RequiresZeroInit, ConstructKind); + RequiresZeroInit, ConstructKind, + ParenRange); } /// \brief Build a new object-construction expression. @@ -5725,7 +5727,8 @@ TreeTransform::TransformCXXConstructExpr(CXXConstructExpr *E) { Constructor, E->isElidable(), move_arg(Args), E->requiresZeroInitialization(), - E->getConstructionKind()); + E->getConstructionKind(), + E->getParenRange()); } /// \brief Transform a C++ temporary-binding expression. diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index f1137c0e3386..4011fa8c1cd3 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1001,12 +1001,12 @@ void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) { E->setElidable(Record[Idx++]); E->setRequiresZeroInitialization(Record[Idx++]); E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]); + E->ParenRange = ReadSourceRange(Record, Idx); } void ASTStmtReader::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { VisitCXXConstructExpr(E); E->Type = GetTypeSourceInfo(Record, Idx); - E->RParenLoc = ReadSourceLocation(Record, Idx); } void ASTStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { @@ -1122,9 +1122,11 @@ void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) { TypeIdParens.setBegin(ReadSourceLocation(Record, Idx)); TypeIdParens.setEnd(ReadSourceLocation(Record, Idx)); E->TypeIdParens = TypeIdParens; - E->setStartLoc(ReadSourceLocation(Record, Idx)); - E->setEndLoc(ReadSourceLocation(Record, Idx)); - + E->StartLoc = ReadSourceLocation(Record, Idx); + E->EndLoc = ReadSourceLocation(Record, Idx); + E->ConstructorLParen = ReadSourceLocation(Record, Idx); + E->ConstructorRParen = ReadSourceLocation(Record, Idx); + E->AllocateArgsArray(*Reader.getContext(), isArray, NumPlacementArgs, NumCtorArgs); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 657cd68343f1..33b70e98c06d 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -978,13 +978,13 @@ void ASTStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) { Record.push_back(E->isElidable()); Record.push_back(E->requiresZeroInitialization()); Record.push_back(E->getConstructionKind()); // FIXME: stable encoding + Writer.AddSourceRange(E->getParenRange(), Record); Code = serialization::EXPR_CXX_CONSTRUCT; } void ASTStmtWriter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { VisitCXXConstructExpr(E); Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); Code = serialization::EXPR_CXX_TEMPORARY_OBJECT; } @@ -1113,6 +1113,8 @@ void ASTStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) { Writer.AddSourceRange(E->getTypeIdParens(), Record); Writer.AddSourceLocation(E->getStartLoc(), Record); Writer.AddSourceLocation(E->getEndLoc(), Record); + Writer.AddSourceLocation(E->getConstructorLParen(), Record); + Writer.AddSourceLocation(E->getConstructorRParen(), Record); for (CXXNewExpr::arg_iterator I = E->raw_arg_begin(), e = E->raw_arg_end(); I != e; ++I) Writer.AddStmt(*I); diff --git a/clang/test/Index/load-stmts.cpp b/clang/test/Index/load-stmts.cpp index 49791222cf4a..d4febab6672e 100644 --- a/clang/test/Index/load-stmts.cpp +++ b/clang/test/Index/load-stmts.cpp @@ -215,7 +215,7 @@ void considered_harmful(int x) { // CHECK: load-stmts.cpp:104:5: MemberRef=member:100:7 Extent=[104:5 - 104:11] // CHECK: load-stmts.cpp:104:12: DeclRefExpr=x:103:22 Extent=[104:12 - 104:13] // CHECK: load-stmts.cpp:104:16: TypeRef=struct Base:94:8 Extent=[104:16 - 104:2 -// CHECK: load-stmts.cpp:104:16: CallExpr= Extent=[104:16 - 104:22] +// CHECK: load-stmts.cpp:104:16: CallExpr= Extent=[104:16 - 104:23] // CHECK: load-stmts.cpp:104:21: DeclRefExpr=x:103:22 Extent=[104:21 - 104:22] // CHECK: load-stmts.cpp:107:6: FunctionDecl=considered_harmful:107:6 (Definition) // CHECK: load-stmts.cpp:108:2: LabelStmt=start_over Extent=[108:2 - 109:28]