diff --git a/clang/clang.xcodeproj/project.pbxproj b/clang/clang.xcodeproj/project.pbxproj index 850cfd792f6a..3f00073f8802 100644 --- a/clang/clang.xcodeproj/project.pbxproj +++ b/clang/clang.xcodeproj/project.pbxproj @@ -46,6 +46,7 @@ 1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; }; 1A986AB710D0746D00A8EA9E /* CGDeclCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */; }; 1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */; }; + 1AA963C410D85A7300786C86 /* FullExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA963C310D85A7300786C86 /* FullExpr.cpp */; }; 1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */; }; 1ADD795410A90C6100741BBA /* TypePrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795110A90C6100741BBA /* TypePrinter.cpp */; }; 1ADD795510A90C6100741BBA /* TypeLoc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795210A90C6100741BBA /* TypeLoc.cpp */; }; @@ -400,6 +401,8 @@ 1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGDeclCXX.cpp; path = lib/CodeGen/CGDeclCXX.cpp; sourceTree = ""; tabWidth = 2; }; 1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = RecordLayoutBuilder.cpp; path = lib/AST/RecordLayoutBuilder.cpp; sourceTree = ""; tabWidth = 2; }; 1AA1D91710125DE30078DEBC /* RecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = RecordLayoutBuilder.h; path = lib/AST/RecordLayoutBuilder.h; sourceTree = ""; tabWidth = 2; }; + 1AA963AB10D8576800786C86 /* FullExpr.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = FullExpr.h; path = clang/AST/FullExpr.h; sourceTree = ""; tabWidth = 2; }; + 1AA963C310D85A7300786C86 /* FullExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FullExpr.cpp; path = lib/AST/FullExpr.cpp; sourceTree = ""; }; 1AB290021045858B00FE33D8 /* PartialDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = PartialDiagnostic.h; sourceTree = ""; tabWidth = 2; }; 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGBuiltin.cpp; path = lib/CodeGen/CGBuiltin.cpp; sourceTree = ""; tabWidth = 2; }; 1ADD795110A90C6100741BBA /* TypePrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypePrinter.cpp; path = lib/AST/TypePrinter.cpp; sourceTree = ""; }; @@ -1348,6 +1351,7 @@ DE0FCA620A95859D00248FD5 /* Expr.h */, 1A30A9E80B93A4C800201A91 /* ExprCXX.h */, 35CEA05A0DF9E82700A41296 /* ExprObjC.h */, + 1AA963AB10D8576800786C86 /* FullExpr.h */, DEDFE5CB0F7206CC0035BD10 /* NestedNameSpecifier.h */, 35EE48AE0E0C4CB200715C54 /* ParentMap.h */, 3547129D0C88881300B3E1D5 /* PrettyPrinter.h */, @@ -1385,6 +1389,7 @@ DE0FCB330A9C21F100248FD5 /* Expr.cpp */, 1A32C17E0E1C87AD00A6B483 /* ExprConstant.cpp */, 35260CA40C7F75C000D66CE9 /* ExprCXX.cpp */, + 1AA963C310D85A7300786C86 /* FullExpr.cpp */, 3557D1A80EB136B100C59739 /* InheritViz.cpp */, DEDFE5CE0F7206E40035BD10 /* NestedNameSpecifier.cpp */, 35EE48B00E0C4CCA00715C54 /* ParentMap.cpp */, @@ -1929,6 +1934,7 @@ 1ADD795610A90C6100741BBA /* TemplateBase.cpp in Sources */, 1A986AB710D0746D00A8EA9E /* CGDeclCXX.cpp in Sources */, E16B523510D30B2400430AC9 /* cc1_main.cpp in Sources */, + 1AA963C410D85A7300786C86 /* FullExpr.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/clang/include/clang/AST/FullExpr.h b/clang/include/clang/AST/FullExpr.h new file mode 100644 index 000000000000..727036a5cfc5 --- /dev/null +++ b/clang/include/clang/AST/FullExpr.h @@ -0,0 +1,51 @@ +//===--- FullExpr.h - C++ full expression class -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the FullExpr interface, to be used for type safe handling +// of full expressions. +// +// Full expressions are described in C++ [intro.execution]p12. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_FULLEXPR_H +#define LLVM_CLANG_AST_FULLEXPR_H + +#include "llvm/ADT/PointerUnion.h" + +namespace clang { + class ASTContext; + class CXXTemporary; + class Expr; + + class FullExpr { + struct ExprAndTemporaries { + Expr *SubExpr; + + unsigned NumTemps; + + typedef CXXTemporary** iterator; + + iterator begin() { return reinterpret_cast(this + 1); } + iterator end() { return begin() + NumTemps; } + + }; + + llvm::PointerUnion SubExpr; + + FullExpr() { } + + public: + static FullExpr Create(ASTContext &Context, Expr *SubExpr, + CXXTemporary **Temps, unsigned NumTemps); + }; + + +} // end namespace clang + +#endif diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index d6f6a834d9c1..30a4cf7f580a 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -20,6 +20,7 @@ #include "clang/AST/PrettyPrinter.h" #include "clang/AST/StmtIterator.h" #include "clang/AST/DeclGroup.h" +#include "clang/AST/FullExpr.h" #include "llvm/ADT/SmallVector.h" #include "clang/AST/ASTContext.h" #include diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index b7540f9993d0..92044a0d3975 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -131,7 +131,7 @@ public: }; template - FullExprArg FullExpr(T &Arg) { + FullExprArg MakeFullExpr(T &Arg) { return FullExprArg(ActOnFinishFullExpr(move(Arg))); } diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 0f0b22d65f6f..5aecf878c920 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -16,6 +16,7 @@ add_clang_library(clangAST Expr.cpp ExprCXX.cpp ExprConstant.cpp + FullExpr.cpp InheritViz.cpp NestedNameSpecifier.cpp ParentMap.cpp diff --git a/clang/lib/AST/FullExpr.cpp b/clang/lib/AST/FullExpr.cpp new file mode 100644 index 000000000000..39c3bad0a77e --- /dev/null +++ b/clang/lib/AST/FullExpr.cpp @@ -0,0 +1,42 @@ +//===--- FullExpr.cpp - C++ full expression class ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the FullExpr interface, to be used for type safe handling +// of full expressions. +// +// Full expressions are described in C++ [intro.execution]p12. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTContext.h" +#include "clang/AST/FullExpr.h" +#include "llvm/Support/AlignOf.h" +using namespace clang; + +FullExpr FullExpr::Create(ASTContext &Context, Expr *SubExpr, + CXXTemporary **Temporaries, unsigned NumTemporaries) { + FullExpr E; + + if (!NumTemporaries) { + E.SubExpr = SubExpr; + return E; + } + + unsigned Size = sizeof(FullExpr) + + sizeof(CXXTemporary *) * NumTemporaries; + + unsigned Align = llvm::AlignOf::Alignment; + ExprAndTemporaries *ET = + static_cast(Context.Allocate(Size, Align)); + + ET->SubExpr = SubExpr; + std::copy(Temporaries, Temporaries + NumTemporaries, ET->begin()); + + return E; +} diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 2c53847f8ed0..9904a2ca85dc 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -1589,7 +1589,7 @@ Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) { // Otherwise, eat the semicolon. ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr); - return Actions.ActOnExprStmt(Actions.FullExpr(Res)); + return Actions.ActOnExprStmt(Actions.MakeFullExpr(Res)); } Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index a2ac64655502..4fc443c78ba2 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -131,7 +131,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) { } // Otherwise, eat the semicolon. ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr); - return Actions.ActOnExprStmt(Actions.FullExpr(Expr)); + return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr)); } case tok::kw_case: // C99 6.8.1: labeled-statement @@ -494,7 +494,7 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { // Eat the semicolon at the end of stmt and convert the expr into a // statement. ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr); - R = Actions.ActOnExprStmt(Actions.FullExpr(Res)); + R = Actions.ActOnExprStmt(Actions.MakeFullExpr(Res)); } } @@ -593,7 +593,7 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) { if (ParseParenExprOrCondition(CondExp, CondVar)) return StmtError(); - FullExprArg FullCondExp(Actions.FullExpr(CondExp)); + FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp)); // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this @@ -720,7 +720,7 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) { if (ParseParenExprOrCondition(Cond, CondVar)) return StmtError(); - FullExprArg FullCond(Actions.FullExpr(Cond)); + FullExprArg FullCond(Actions.MakeFullExpr(Cond)); OwningStmtResult Switch = Actions.ActOnStartOfSwitchStmt(FullCond, CondVar); @@ -801,7 +801,7 @@ Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) { if (ParseParenExprOrCondition(Cond, CondVar)) return StmtError(); - FullExprArg FullCond(Actions.FullExpr(Cond)); + FullExprArg FullCond(Actions.MakeFullExpr(Cond)); // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this @@ -993,7 +993,7 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) { // Turn the expression into a stmt. if (!Value.isInvalid()) - FirstPart = Actions.ActOnExprStmt(Actions.FullExpr(Value)); + FirstPart = Actions.ActOnExprStmt(Actions.MakeFullExpr(Value)); if (Tok.is(tok::semi)) { ConsumeToken(); @@ -1060,8 +1060,8 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) { if (!ForEach) return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart), - Actions.FullExpr(SecondPart), SecondVar, - Actions.FullExpr(ThirdPart), RParenLoc, + Actions.MakeFullExpr(SecondPart), SecondVar, + Actions.MakeFullExpr(ThirdPart), RParenLoc, move(Body)); return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 0472d50ea578..88f290a9d806 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -24,6 +24,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/FullExpr.h" #include "clang/Parse/Action.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallVector.h" @@ -2005,6 +2006,8 @@ public: /// Otherwise, just returs the passed in expression. Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr); + FullExpr CreateFullExpr(Expr *SubExpr); + virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr); bool RequireCompleteDeclContext(const CXXScopeSpec &SS); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 80b64306540f..4bcb0583c6da 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -2102,6 +2102,22 @@ Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr) { return E; } +FullExpr Sema::CreateFullExpr(Expr *SubExpr) { + unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries; + assert(ExprTemporaries.size() >= FirstTemporary); + + unsigned NumTemporaries = ExprTemporaries.size() - FirstTemporary; + CXXTemporary **Temporaries = + NumTemporaries == 0 ? 0 : &ExprTemporaries[FirstTemporary]; + + FullExpr E = FullExpr::Create(Context, SubExpr, Temporaries, NumTemporaries); + + ExprTemporaries.erase(ExprTemporaries.begin() + FirstTemporary, + ExprTemporaries.end()); + + return E; +} + Sema::OwningExprResult Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc, tok::TokenKind OpKind, TypeTy *&ObjectType) { diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index cc5722297fc4..03169bf3800d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1655,7 +1655,7 @@ Sema::OwningStmtResult TreeTransform::TransformStmt(Stmt *S) { if (E.isInvalid()) return getSema().StmtError(); - return getSema().ActOnExprStmt(getSema().FullExpr(E)); + return getSema().ActOnExprStmt(getSema().MakeFullExpr(E)); } } @@ -3067,7 +3067,7 @@ TreeTransform::TransformIfStmt(IfStmt *S) { return SemaRef.StmtError(); } - Sema::FullExprArg FullCond(getSema().FullExpr(Cond)); + Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond)); // Transform the "then" branch. OwningStmtResult Then = getDerived().TransformStmt(S->getThen()); @@ -3110,7 +3110,7 @@ TreeTransform::TransformSwitchStmt(SwitchStmt *S) { return SemaRef.StmtError(); } - Sema::FullExprArg FullCond(getSema().FullExpr(Cond)); + Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond)); // Rebuild the switch statement. OwningStmtResult Switch = getDerived().RebuildSwitchStmtStart(FullCond, @@ -3147,7 +3147,7 @@ TreeTransform::TransformWhileStmt(WhileStmt *S) { return SemaRef.StmtError(); } - Sema::FullExprArg FullCond(getSema().FullExpr(Cond)); + Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond)); // Transform the body OwningStmtResult Body = getDerived().TransformStmt(S->getBody()); @@ -3229,9 +3229,9 @@ TreeTransform::TransformForStmt(ForStmt *S) { return SemaRef.Owned(S->Retain()); return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(), - move(Init), getSema().FullExpr(Cond), + move(Init), getSema().MakeFullExpr(Cond), ConditionVar, - getSema().FullExpr(Inc), + getSema().MakeFullExpr(Inc), S->getRParenLoc(), move(Body)); }