[cfe-commits] r150318 - in /cfe/trunk: include/clang/AST/ include/clang/Sema/ lib/AST/ lib/CodeGen/ lib/Parse/ lib/Sema/ lib/Serialization/ test/CXX/temp/temp.decls/temp.variadic/ test/Sema/ test/SemaTemplate/
Sebastian Redl
sebastian.redl at getdesigned.at
Sat Feb 11 15:51:48 PST 2012
Author: cornedbee
Date: Sat Feb 11 17:51:47 2012
New Revision: 150318
URL: http://llvm.org/viewvc/llvm-project?rev=150318&view=rev
Log:
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
Added:
cfe/trunk/test/SemaTemplate/nested-incomplete-class.cpp
Removed:
cfe/trunk/include/clang/Sema/MultiInitializer.h
cfe/trunk/lib/Sema/MultiInitializer.cpp
cfe/trunk/test/Sema/paren-list-expr-type.cpp
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/include/clang/AST/ExprCXX.h
cfe/trunk/include/clang/Sema/Initialization.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/AST/DeclPrinter.cpp
cfe/trunk/lib/AST/DumpXML.cpp
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/ExprCXX.cpp
cfe/trunk/lib/CodeGen/CGObjC.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Sema/CMakeLists.txt
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Sat Feb 11 17:51:47 2012
@@ -681,6 +681,13 @@
/// It is illegal to call this function with SC == None.
static const char *getStorageClassSpecifierString(StorageClass SC);
+ /// \brief Initialization styles.
+ enum InitializationStyle {
+ CInit, ///< C-style initialization with assignment
+ CallInit, ///< Call-style initialization (C++98)
+ ListInit ///< Direct list-initialization (C++11)
+ };
+
protected:
/// \brief Placeholder type used in Init to denote an unparsed C++ default
/// argument.
@@ -706,7 +713,7 @@
unsigned SClass : 3;
unsigned SClassAsWritten : 3;
unsigned ThreadSpecified : 1;
- unsigned HasCXXDirectInit : 1;
+ unsigned InitStyle : 2;
/// \brief Whether this variable is the exception variable in a C++ catch
/// or an Objective-C @catch statement.
@@ -728,7 +735,7 @@
/// \brief Whether this variable is (C++0x) constexpr.
unsigned IsConstexpr : 1;
};
- enum { NumVarDeclBits = 13 };
+ enum { NumVarDeclBits = 14 };
friend class ASTDeclReader;
friend class StmtIteratorBase;
@@ -756,7 +763,7 @@
/// Otherwise, the number of function parameter scopes enclosing
/// the function parameter scope in which this parameter was
/// declared.
- unsigned ScopeDepthOrObjCQuals : 8;
+ unsigned ScopeDepthOrObjCQuals : 7;
/// The number of parameters preceding this parameter in the
/// function parameter scope in which it was declared.
@@ -1073,16 +1080,27 @@
/// declaration is an integral constant expression.
bool checkInitIsICE() const;
- void setCXXDirectInitializer(bool T) { VarDeclBits.HasCXXDirectInit = T; }
+ void setInitStyle(InitializationStyle Style) {
+ VarDeclBits.InitStyle = Style;
+ }
- /// hasCXXDirectInitializer - If true, the initializer was a direct
- /// initializer, e.g: "int x(1);". The Init expression will be the expression
- /// inside the parens or a "ClassType(a,b,c)" class constructor expression for
- /// class types. Clients can distinguish between "int x(1);" and "int x=1;"
- /// by checking hasCXXDirectInitializer.
+ /// \brief The style of initialization for this declaration.
///
- bool hasCXXDirectInitializer() const {
- return VarDeclBits.HasCXXDirectInit;
+ /// C-style initialization is "int x = 1;". Call-style initialization is
+ /// a C++98 direct-initializer, e.g. "int x(1);". The Init expression will be
+ /// the expression inside the parens or a "ClassType(a,b,c)" class constructor
+ /// expression for class types. List-style initialization is C++11 syntax,
+ /// e.g. "int x{1};". Clients can distinguish between different forms of
+ /// initialization by checking this value. In particular, "int x = {1};" is
+ /// C-style, "int x({1})" is call-style, and "int x{1};" is list-style; the
+ /// Init expression in all three cases is an InitListExpr.
+ InitializationStyle getInitStyle() const {
+ return static_cast<InitializationStyle>(VarDeclBits.InitStyle);
+ }
+
+ /// \brief Whether the initializer is a direct-initializer (list or call).
+ bool isDirectInit() const {
+ return getInitStyle() != CInit;
}
/// \brief Determine whether this variable is the exception variable in a
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Sat Feb 11 17:51:47 2012
@@ -3977,7 +3977,7 @@
public:
ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs,
- unsigned numexprs, SourceLocation rparenloc, QualType T);
+ unsigned numexprs, SourceLocation rparenloc);
/// \brief Build an empty paren list.
explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { }
Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Sat Feb 11 17:51:47 2012
@@ -812,6 +812,7 @@
unsigned NumArgs : 16;
bool Elidable : 1;
bool HadMultipleCandidates : 1;
+ bool ListInitialization : 1;
bool ZeroInitialization : 1;
unsigned ConstructKind : 2;
Stmt **Args;
@@ -822,32 +823,36 @@
CXXConstructorDecl *d, bool elidable,
Expr **args, unsigned numargs,
bool HadMultipleCandidates,
- bool ZeroInitialization = false,
- ConstructionKind ConstructKind = CK_Complete,
- SourceRange ParenRange = SourceRange());
+ bool ListInitialization,
+ bool ZeroInitialization,
+ ConstructionKind ConstructKind,
+ SourceRange ParenRange);
/// \brief Construct an empty C++ construction expression.
CXXConstructExpr(StmtClass SC, EmptyShell Empty)
- : Expr(SC, Empty), Constructor(0), NumArgs(0), Elidable(0),
- HadMultipleCandidates(false), ZeroInitialization(0),
- ConstructKind(0), Args(0) { }
+ : Expr(SC, Empty), Constructor(0), NumArgs(0), Elidable(false),
+ HadMultipleCandidates(false), ListInitialization(false),
+ ZeroInitialization(false), ConstructKind(0), Args(0)
+ { }
public:
/// \brief Construct an empty C++ construction expression.
explicit CXXConstructExpr(EmptyShell Empty)
: Expr(CXXConstructExprClass, Empty), Constructor(0),
- NumArgs(0), Elidable(0), HadMultipleCandidates(false),
- ZeroInitialization(0), ConstructKind(0), Args(0) { }
+ NumArgs(0), Elidable(false), HadMultipleCandidates(false),
+ ListInitialization(false), ZeroInitialization(false),
+ ConstructKind(0), Args(0)
+ { }
static CXXConstructExpr *Create(ASTContext &C, QualType T,
SourceLocation Loc,
CXXConstructorDecl *D, bool Elidable,
Expr **Args, unsigned NumArgs,
bool HadMultipleCandidates,
- bool ZeroInitialization = false,
- ConstructionKind ConstructKind = CK_Complete,
- SourceRange ParenRange = SourceRange());
-
+ bool ListInitialization,
+ bool ZeroInitialization,
+ ConstructionKind ConstructKind,
+ SourceRange ParenRange);
CXXConstructorDecl* getConstructor() const { return Constructor; }
void setConstructor(CXXConstructorDecl *C) { Constructor = C; }
@@ -864,6 +869,10 @@
bool hadMultipleCandidates() const { return HadMultipleCandidates; }
void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; }
+ /// \brief Whether this constructor call was written as list-initialization.
+ bool isListInitialization() const { return ListInitialization; }
+ void setListInitialization(bool V) { ListInitialization = V; }
+
/// \brief Whether this construction first requires
/// zero-initialization before the initializer is called.
bool requiresZeroInitialization() const { return ZeroInitialization; }
Modified: cfe/trunk/include/clang/Sema/Initialization.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Initialization.h (original)
+++ cfe/trunk/include/clang/Sema/Initialization.h Sat Feb 11 17:51:47 2012
@@ -326,20 +326,22 @@
public:
/// \brief The kind of initialization being performed.
enum InitKind {
- IK_Direct, ///< Direct initialization
- IK_Copy, ///< Copy initialization
- IK_Default, ///< Default initialization
- IK_Value ///< Value initialization
+ IK_Direct, ///< Direct initialization
+ IK_DirectList, ///< Direct list-initialization
+ IK_Copy, ///< Copy initialization
+ IK_Default, ///< Default initialization
+ IK_Value ///< Value initialization
};
private:
/// \brief The kind of initialization that we're storing.
enum StoredInitKind {
- SIK_Direct = IK_Direct, ///< Direct initialization
- SIK_Copy = IK_Copy, ///< Copy initialization
- SIK_Default = IK_Default, ///< Default initialization
- SIK_Value = IK_Value, ///< Value initialization
- SIK_ImplicitValue, ///< Implicit value initialization
+ SIK_Direct = IK_Direct, ///< Direct initialization
+ SIK_DirectList = IK_DirectList, ///< Direct list-initialization
+ SIK_Copy = IK_Copy, ///< Copy initialization
+ SIK_Default = IK_Default, ///< Default initialization
+ SIK_Value = IK_Value, ///< Value initialization
+ SIK_ImplicitValue, ///< Implicit value initialization
SIK_DirectCast, ///< Direct initialization due to a cast
/// \brief Direct initialization due to a C-style cast.
SIK_DirectCStyleCast,
@@ -370,6 +372,10 @@
return InitializationKind(SIK_Direct, InitLoc, LParenLoc, RParenLoc);
}
+ static InitializationKind CreateDirectList(SourceLocation InitLoc) {
+ return InitializationKind(SIK_DirectList, InitLoc, InitLoc, InitLoc);
+ }
+
/// \brief Create a direct initialization due to a cast that isn't a C-style
/// or functional cast.
static InitializationKind CreateCast(SourceRange TypeRange) {
Removed: cfe/trunk/include/clang/Sema/MultiInitializer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/MultiInitializer.h?rev=150317&view=auto
==============================================================================
--- cfe/trunk/include/clang/Sema/MultiInitializer.h (original)
+++ cfe/trunk/include/clang/Sema/MultiInitializer.h (removed)
@@ -1,72 +0,0 @@
-//===--- MultiInitializer.h - Initializer expression group ------*- 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 MultiInitializer class, which can represent a list
-// initializer or a parentheses-wrapped group of expressions in a C++ member
-// initializer.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SEMA_MULTIINITIALIZER_H
-#define LLVM_CLANG_SEMA_MULTIINITIALIZER_H
-
-#include "clang/Sema/Ownership.h"
-#include "clang/Basic/SourceLocation.h"
-#include "llvm/ADT/PointerUnion.h"
-
-namespace clang {
- class ASTContext;
- class Expr;
- class InitializationKind;
- class InitializedEntity;
- class InitListExpr;
- class Sema;
-
-class MultiInitializer {
- llvm::PointerUnion<Expr*, Expr**> InitListOrExpressions;
- unsigned NumInitializers;
- SourceLocation LParenLoc;
- SourceLocation RParenLoc;
-
- InitListExpr *getInitList() const;
- Expr **getExpressions() const { return InitListOrExpressions.get<Expr**>(); }
-
-public:
- MultiInitializer(Expr* InitList)
- : InitListOrExpressions(InitList)
- {}
-
- MultiInitializer(SourceLocation LParenLoc, Expr **Exprs, unsigned NumInits,
- SourceLocation RParenLoc)
- : InitListOrExpressions(Exprs), NumInitializers(NumInits),
- LParenLoc(LParenLoc), RParenLoc(RParenLoc)
- {}
-
- bool isInitializerList() const { return InitListOrExpressions.is<Expr*>(); }
-
- SourceLocation getStartLoc() const;
- SourceLocation getEndLoc() const;
-
- typedef Expr **iterator;
- iterator begin() const;
- iterator end() const;
-
- bool isTypeDependent() const;
-
- bool DiagnoseUnexpandedParameterPack(Sema &SemaRef) const;
-
- // Return the InitListExpr or create a ParenListExpr.
- Expr *CreateInitExpr(ASTContext &Ctx, QualType T) const;
-
- ExprResult PerformInit(Sema &SemaRef, InitializedEntity Entity,
- InitializationKind Kind) const;
-};
-}
-
-#endif
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sat Feb 11 17:51:47 2012
@@ -22,7 +22,6 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/LocInfoType.h"
-#include "clang/Sema/MultiInitializer.h"
#include "clang/Sema/TypoCorrection.h"
#include "clang/Sema/Weak.h"
#include "clang/AST/Expr.h"
@@ -2387,9 +2386,9 @@
ExprResult ActOnNumericConstant(const Token &Tok);
ExprResult ActOnCharacterConstant(const Token &Tok);
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E);
- ExprResult ActOnParenOrParenListExpr(SourceLocation L,
- SourceLocation R,
- MultiExprArg Val);
+ ExprResult ActOnParenListExpr(SourceLocation L,
+ SourceLocation R,
+ MultiExprArg Val);
/// ActOnStringLiteral - The specified tokens were lexed as pasted string
/// fragments (e.g. "foo" "bar" L"baz").
@@ -2769,15 +2768,6 @@
UnqualifiedId &Name,
TypeResult Type);
- /// AddCXXDirectInitializerToDecl - This action is called immediately after
- /// ActOnDeclarator, when a C++ direct initializer is present.
- /// e.g: "int x(1);"
- void AddCXXDirectInitializerToDecl(Decl *Dcl,
- SourceLocation LParenLoc,
- MultiExprArg Exprs,
- SourceLocation RParenLoc,
- bool TypeMayContainAuto);
-
/// InitializeVarWithConstructor - Creates an CXXConstructExpr
/// and sets it as the initializer for the the passed in VarDecl.
bool InitializeVarWithConstructor(VarDecl *VD,
@@ -3574,21 +3564,21 @@
ParsedType TemplateTypeTy,
const DeclSpec &DS,
SourceLocation IdLoc,
- const MultiInitializer &Init,
+ Expr *Init,
SourceLocation EllipsisLoc);
MemInitResult BuildMemberInitializer(ValueDecl *Member,
- const MultiInitializer &Args,
+ Expr *Init,
SourceLocation IdLoc);
MemInitResult BuildBaseInitializer(QualType BaseType,
TypeSourceInfo *BaseTInfo,
- const MultiInitializer &Args,
+ Expr *Init,
CXXRecordDecl *ClassDecl,
SourceLocation EllipsisLoc);
MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo,
- const MultiInitializer &Args,
+ Expr *Init,
CXXRecordDecl *ClassDecl);
bool SetDelegatingInitializer(CXXConstructorDecl *Constructor,
@@ -5186,6 +5176,10 @@
Decl *SubstDecl(Decl *D, DeclContext *Owner,
const MultiLevelTemplateArgumentList &TemplateArgs);
+ ExprResult SubstInitializer(Expr *E,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool CXXDirectInit);
+
bool
SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
CXXRecordDecl *Pattern,
@@ -5259,11 +5253,6 @@
void InstantiateMemInitializers(CXXConstructorDecl *New,
const CXXConstructorDecl *Tmpl,
const MultiLevelTemplateArgumentList &TemplateArgs);
- bool InstantiateInitializer(Expr *Init,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- SourceLocation &LParenLoc,
- ASTOwningVector<Expr*> &NewArgs,
- SourceLocation &RParenLoc);
NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
const MultiLevelTemplateArgumentList &TemplateArgs);
Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Sat Feb 11 17:51:47 2012
@@ -621,16 +621,20 @@
Out << Name;
Expr *Init = D->getInit();
if (!Policy.SuppressInitializers && Init) {
- if (D->hasCXXDirectInitializer())
- Out << "(";
- else {
- CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init);
- if (!CCE || CCE->getConstructor()->isCopyOrMoveConstructor())
- Out << " = ";
- }
- Init->printPretty(Out, Context, 0, Policy, Indentation);
- if (D->hasCXXDirectInitializer())
- Out << ")";
+ bool ImplicitInit = false;
+ if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init))
+ ImplicitInit = D->getInitStyle() == VarDecl::CallInit &&
+ Construct->getNumArgs() == 0 && !Construct->isListInitialization();
+ if (!ImplicitInit) {
+ if (D->getInitStyle() == VarDecl::CallInit)
+ Out << "(";
+ else if (D->getInitStyle() == VarDecl::CInit) {
+ Out << " = ";
+ }
+ Init->printPretty(Out, Context, 0, Policy, Indentation);
+ if (D->getInitStyle() == VarDecl::CallInit)
+ Out << ")";
+ }
}
prettyPrintAttributes(D);
}
Modified: cfe/trunk/lib/AST/DumpXML.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DumpXML.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DumpXML.cpp (original)
+++ cfe/trunk/lib/AST/DumpXML.cpp Sat Feb 11 17:51:47 2012
@@ -461,7 +461,13 @@
if (D->getStorageClass() != SC_None)
set("storage",
VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
- setFlag("directinit", D->hasCXXDirectInitializer());
+ StringRef initStyle = "";
+ switch (D->getInitStyle()) {
+ case VarDecl::CInit: initStyle = "c"; break;
+ case VarDecl::CallInit: initStyle = "call"; break;
+ case VarDecl::ListInit: initStyle = "list"; break;
+ }
+ set("initstyle", initStyle);
setFlag("nrvo", D->isNRVOVariable());
// TODO: instantiation, etc.
}
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Sat Feb 11 17:51:47 2012
@@ -3414,11 +3414,10 @@
ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
Expr **exprs, unsigned nexprs,
- SourceLocation rparenloc, QualType T)
- : Expr(ParenListExprClass, T, VK_RValue, OK_Ordinary,
+ SourceLocation rparenloc)
+ : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary,
false, false, false, false),
NumExprs(nexprs), LParenLoc(lparenloc), RParenLoc(rparenloc) {
- assert(!T.isNull() && "ParenListExpr must have a valid type");
Exprs = new (C) Stmt*[nexprs];
for (unsigned i = 0; i != nexprs; ++i) {
if (exprs[i]->isTypeDependent())
Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Sat Feb 11 17:51:47 2012
@@ -653,7 +653,7 @@
Type->getType().getNonReferenceType(),
Type->getTypeLoc().getBeginLoc(),
Cons, false, Args, NumArgs,
- HadMultipleCandidates, ZeroInitialization,
+ HadMultipleCandidates, /*FIXME*/false, ZeroInitialization,
CXXConstructExpr::CK_Complete, parenRange),
Type(Type) {
}
@@ -668,13 +668,15 @@
CXXConstructorDecl *D, bool Elidable,
Expr **Args, unsigned NumArgs,
bool HadMultipleCandidates,
+ bool ListInitialization,
bool ZeroInitialization,
ConstructionKind ConstructKind,
SourceRange ParenRange) {
return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D,
Elidable, Args, NumArgs,
- HadMultipleCandidates, ZeroInitialization,
- ConstructKind, ParenRange);
+ HadMultipleCandidates, ListInitialization,
+ ZeroInitialization, ConstructKind,
+ ParenRange);
}
CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
@@ -682,6 +684,7 @@
CXXConstructorDecl *D, bool elidable,
Expr **args, unsigned numargs,
bool HadMultipleCandidates,
+ bool ListInitialization,
bool ZeroInitialization,
ConstructionKind ConstructKind,
SourceRange ParenRange)
@@ -691,6 +694,7 @@
T->containsUnexpandedParameterPack()),
Constructor(D), Loc(Loc), ParenRange(ParenRange), NumArgs(numargs),
Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates),
+ ListInitialization(ListInitialization),
ZeroInitialization(ZeroInitialization),
ConstructKind(ConstructKind), Args(0)
{
Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Sat Feb 11 17:51:47 2012
@@ -2740,7 +2740,8 @@
CXXConstExpr->getConstructor(),
CXXConstExpr->isElidable(),
&ConstructorArgs[0], ConstructorArgs.size(),
- CXXConstExpr->hadMultipleCandidates(),
+ CXXConstExpr->hadMultipleCandidates(),
+ CXXConstExpr->isListInitialization(),
CXXConstExpr->requiresZeroInitialization(),
CXXConstExpr->getConstructionKind(), SourceRange());
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat Feb 11 17:51:47 2012
@@ -1344,10 +1344,11 @@
ExitScope();
}
- Actions.AddCXXDirectInitializerToDecl(ThisDecl, T.getOpenLocation(),
- move_arg(Exprs),
- T.getCloseLocation(),
- TypeContainsAuto);
+ ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(),
+ T.getCloseLocation(),
+ move_arg(Exprs));
+ Actions.AddInitializerToDecl(ThisDecl, Initializer.take(),
+ /*DirectInit=*/true, TypeContainsAuto);
}
} else if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) {
// Parse C++0x braced-init-list.
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Sat Feb 11 17:51:47 2012
@@ -2006,8 +2006,8 @@
if (!ParseExpressionList(ArgExprs, CommaLocs)) {
ExprType = SimpleExpr;
- Result = Actions.ActOnParenOrParenListExpr(OpenLoc, Tok.getLocation(),
- move_arg(ArgExprs));
+ Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
+ move_arg(ArgExprs));
}
} else {
InMessageExpressionRAIIObject InMessage(*this, false);
Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Sat Feb 11 17:51:47 2012
@@ -8,7 +8,6 @@
DelayedDiagnostic.cpp
IdentifierResolver.cpp
JumpDiagnostics.cpp
- MultiInitializer.cpp
Scope.cpp
Sema.cpp
SemaAccess.cpp
Removed: cfe/trunk/lib/Sema/MultiInitializer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/MultiInitializer.cpp?rev=150317&view=auto
==============================================================================
--- cfe/trunk/lib/Sema/MultiInitializer.cpp (original)
+++ cfe/trunk/lib/Sema/MultiInitializer.cpp (removed)
@@ -1,93 +0,0 @@
-//===--- MultiInitializer.cpp - Initializer expression group ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the MultiInitializer class, which can represent a list
-// initializer or a parentheses-wrapped group of expressions in a C++ member
-// initializer.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Sema/MultiInitializer.h"
-#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Sema.h"
-#include "clang/AST/Expr.h"
-
-using namespace clang;
-
-InitListExpr *MultiInitializer::getInitList() const {
- return cast<InitListExpr>(InitListOrExpressions.get<Expr*>());
-}
-
-SourceLocation MultiInitializer::getStartLoc() const {
- return isInitializerList() ? getInitList()->getLBraceLoc() : LParenLoc;
-}
-
-SourceLocation MultiInitializer::getEndLoc() const {
- return isInitializerList() ? getInitList()->getRBraceLoc() : RParenLoc;
-}
-
-MultiInitializer::iterator MultiInitializer::begin() const {
- return isInitializerList() ? getInitList()->getInits() : getExpressions();
-}
-
-MultiInitializer::iterator MultiInitializer::end() const {
- if (isInitializerList()) {
- InitListExpr *ILE = getInitList();
- return ILE->getInits() + ILE->getNumInits();
- }
- return getExpressions() + NumInitializers;
-}
-
-bool MultiInitializer::isTypeDependent() const {
- if (isInitializerList())
- return getInitList()->isTypeDependent();
- for (iterator I = begin(), E = end(); I != E; ++I) {
- if ((*I)->isTypeDependent())
- return true;
- }
- return false;
-}
-
-bool MultiInitializer::DiagnoseUnexpandedParameterPack(Sema &SemaRef) const {
- if (isInitializerList())
- return SemaRef.DiagnoseUnexpandedParameterPack(getInitList(),
- Sema::UPPC_Initializer);
- for (iterator I = begin(), E = end(); I != E; ++I) {
- if (SemaRef.DiagnoseUnexpandedParameterPack(*I, Sema::UPPC_Initializer))
- return true;
- }
- return false;
-}
-
-Expr *MultiInitializer::CreateInitExpr(ASTContext &Ctx, QualType T) const {
- if (isInitializerList())
- return InitListOrExpressions.get<Expr*>();
-
- return new (Ctx) ParenListExpr(Ctx, LParenLoc, getExpressions(),
- NumInitializers, RParenLoc, T);
-}
-
-ExprResult MultiInitializer::PerformInit(Sema &SemaRef,
- InitializedEntity Entity,
- InitializationKind Kind) const {
- Expr *Single;
- Expr **Args;
- unsigned NumArgs;
- if (isInitializerList()) {
- Single = InitListOrExpressions.get<Expr*>();
- Args = &Single;
- NumArgs = 1;
- } else {
- Args = getExpressions();
- NumArgs = NumInitializers;
- }
- InitializationSequence InitSeq(SemaRef, Entity, Kind, Args, NumArgs);
- return InitSeq.Perform(SemaRef, Entity, Kind,
- MultiExprArg(SemaRef, Args, NumArgs), 0);
-}
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Feb 11 17:51:47 2012
@@ -2139,9 +2139,8 @@
/// emitting diagnostics as appropriate.
///
/// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back
-/// to here in AddInitializerToDecl and AddCXXDirectInitializerToDecl. We can't
-/// check them before the initializer is attached.
-///
+/// to here in AddInitializerToDecl. We can't check them before the initializer
+/// is attached.
void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) {
if (New->isInvalidDecl() || Old->isInvalidDecl())
return;
@@ -5983,17 +5982,6 @@
if (RealDecl == 0 || RealDecl->isInvalidDecl())
return;
- // Check for self-references within variable initializers.
- if (VarDecl *vd = dyn_cast<VarDecl>(RealDecl)) {
- // Variables declared within a function/method body are handled
- // by a dataflow analysis.
- if (!vd->hasLocalStorage() && !vd->isStaticLocal())
- CheckSelfReference(RealDecl, Init);
- }
- else {
- CheckSelfReference(RealDecl, Init);
- }
-
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
// With declarators parsed the way they are, the parser cannot
// distinguish between a normal initializer and a pure-specifier.
@@ -6018,12 +6006,44 @@
return;
}
+ // Check for self-references within variable initializers.
+ // Variables declared within a function/method body are handled
+ // by a dataflow analysis.
+ if (!VDecl->hasLocalStorage() && !VDecl->isStaticLocal())
+ CheckSelfReference(RealDecl, Init);
+
+ ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
+
// C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
+ Expr *DeduceInit = Init;
+ // Initializer could be a C++ direct-initializer. Deduction only works if it
+ // contains exactly one expression.
+ if (CXXDirectInit) {
+ if (CXXDirectInit->getNumExprs() == 0) {
+ // It isn't possible to write this directly, but it is possible to
+ // end up in this situation with "auto x(some_pack...);"
+ Diag(CXXDirectInit->getSourceRange().getBegin(),
+ diag::err_auto_var_init_no_expression)
+ << VDecl->getDeclName() << VDecl->getType()
+ << VDecl->getSourceRange();
+ RealDecl->setInvalidDecl();
+ return;
+ } else if (CXXDirectInit->getNumExprs() > 1) {
+ Diag(CXXDirectInit->getExpr(1)->getSourceRange().getBegin(),
+ diag::err_auto_var_init_multiple_expressions)
+ << VDecl->getDeclName() << VDecl->getType()
+ << VDecl->getSourceRange();
+ RealDecl->setInvalidDecl();
+ return;
+ } else {
+ DeduceInit = CXXDirectInit->getExpr(0);
+ }
+ }
TypeSourceInfo *DeducedType = 0;
- if (DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType) ==
+ if (DeduceAutoType(VDecl->getTypeSourceInfo(), DeduceInit, DeducedType) ==
DAR_Failed)
- DiagnoseAutoDeductionFailure(VDecl, Init);
+ DiagnoseAutoDeductionFailure(VDecl, DeduceInit);
if (!DeducedType) {
RealDecl->setInvalidDecl();
return;
@@ -6048,25 +6068,26 @@
return;
}
+ if (!VDecl->getType()->isDependentType()) {
+ // A definition must end up with a complete type, which means it must be
+ // complete with the restriction that an array type might be completed by
+ // the initializer; note that later code assumes this restriction.
+ QualType BaseDeclType = VDecl->getType();
+ if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType))
+ BaseDeclType = Array->getElementType();
+ if (RequireCompleteType(VDecl->getLocation(), BaseDeclType,
+ diag::err_typecheck_decl_incomplete_type)) {
+ RealDecl->setInvalidDecl();
+ return;
+ }
- // A definition must end up with a complete type, which means it must be
- // complete with the restriction that an array type might be completed by the
- // initializer; note that later code assumes this restriction.
- QualType BaseDeclType = VDecl->getType();
- if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType))
- BaseDeclType = Array->getElementType();
- if (RequireCompleteType(VDecl->getLocation(), BaseDeclType,
- diag::err_typecheck_decl_incomplete_type)) {
- RealDecl->setInvalidDecl();
- return;
+ // The variable can not have an abstract class type.
+ if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(),
+ diag::err_abstract_type_in_decl,
+ AbstractVariableType))
+ VDecl->setInvalidDecl();
}
- // The variable can not have an abstract class type.
- if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(),
- diag::err_abstract_type_in_decl,
- AbstractVariableType))
- VDecl->setInvalidDecl();
-
const VarDecl *Def;
if ((Def = VDecl->getDefinition()) && Def != VDecl) {
Diag(VDecl->getLocation(), diag::err_redefinition)
@@ -6128,9 +6149,15 @@
: InitializationKind::CreateCopy(VDecl->getLocation(),
Init->getLocStart());
- InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
+ Expr **Args = &Init;
+ unsigned NumArgs = 1;
+ if (CXXDirectInit) {
+ Args = CXXDirectInit->getExprs();
+ NumArgs = CXXDirectInit->getNumExprs();
+ }
+ InitializationSequence InitSeq(*this, Entity, Kind, Args, NumArgs);
ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
- MultiExprArg(*this, &Init, 1),
+ MultiExprArg(*this, Args,NumArgs),
&DclT);
if (Result.isInvalid()) {
VDecl->setInvalidDecl();
@@ -6266,6 +6293,28 @@
CheckForConstantInitializer(Init, DclT);
}
+ // We will represent direct-initialization similarly to copy-initialization:
+ // int x(1); -as-> int x = 1;
+ // ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c);
+ //
+ // Clients that want to distinguish between the two forms, can check for
+ // direct initializer using VarDecl::getInitStyle().
+ // A major benefit is that clients that don't particularly care about which
+ // exactly form was it (like the CodeGen) can handle both cases without
+ // special case code.
+
+ // C++ 8.5p11:
+ // The form of initialization (using parentheses or '=') is generally
+ // insignificant, but does matter when the entity being initialized has a
+ // class type.
+ if (CXXDirectInit) {
+ assert(DirectInit && "Call-style initializer must be direct init.");
+ VDecl->setInitStyle(VarDecl::CallInit);
+ } else if (DirectInit) {
+ // This must be list-initialization. No other way is direct-initialization.
+ VDecl->setInitStyle(VarDecl::ListInit);
+ }
+
CheckCompleteVariableDeclaration(VDecl);
}
@@ -6496,8 +6545,11 @@
MultiExprArg(*this, 0, 0));
if (Init.isInvalid())
Var->setInvalidDecl();
- else if (Init.get())
+ else if (Init.get()) {
Var->setInit(MaybeCreateExprWithCleanups(Init.get()));
+ // This is important for template substitution.
+ Var->setInitStyle(VarDecl::CallInit);
+ }
CheckCompleteVariableDeclaration(Var);
}
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Feb 11 17:51:47 2012
@@ -1768,7 +1768,7 @@
Expr *InitList,
SourceLocation EllipsisLoc) {
return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
- DS, IdLoc, MultiInitializer(InitList),
+ DS, IdLoc, InitList,
EllipsisLoc);
}
@@ -1785,10 +1785,10 @@
Expr **Args, unsigned NumArgs,
SourceLocation RParenLoc,
SourceLocation EllipsisLoc) {
+ Expr *List = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc);
return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
- DS, IdLoc, MultiInitializer(LParenLoc, Args,
- NumArgs, RParenLoc),
- EllipsisLoc);
+ DS, IdLoc, List, EllipsisLoc);
}
namespace {
@@ -1825,7 +1825,7 @@
ParsedType TemplateTypeTy,
const DeclSpec &DS,
SourceLocation IdLoc,
- const MultiInitializer &Args,
+ Expr *Init,
SourceLocation EllipsisLoc) {
if (!ConstructorD)
return true;
@@ -1864,9 +1864,10 @@
(Member = dyn_cast<IndirectFieldDecl>(*Result.first))) {
if (EllipsisLoc.isValid())
Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
- << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc());
+ << MemberOrBase
+ << SourceRange(IdLoc, Init->getSourceRange().getEnd());
- return BuildMemberInitializer(Member, Args, IdLoc);
+ return BuildMemberInitializer(Member, Init, IdLoc);
}
}
}
@@ -1927,7 +1928,7 @@
Diag(Member->getLocation(), diag::note_previous_decl)
<< CorrectedQuotedStr;
- return BuildMemberInitializer(Member, Args, IdLoc);
+ return BuildMemberInitializer(Member, Init, IdLoc);
} else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) {
const CXXBaseSpecifier *DirectBaseSpec;
const CXXBaseSpecifier *VirtualBaseSpec;
@@ -1955,7 +1956,7 @@
if (!TyD && BaseType.isNull()) {
Diag(IdLoc, diag::err_mem_init_not_member_or_class)
- << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc());
+ << MemberOrBase << SourceRange(IdLoc,Init->getSourceRange().getEnd());
return true;
}
}
@@ -1975,7 +1976,7 @@
if (!TInfo)
TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc);
- return BuildBaseInitializer(BaseType, TInfo, Args, ClassDecl, EllipsisLoc);
+ return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc);
}
/// Checks a member initializer expression for cases where reference (or
@@ -2102,15 +2103,14 @@
}
MemInitResult
-Sema::BuildMemberInitializer(ValueDecl *Member,
- const MultiInitializer &Args,
+Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
SourceLocation IdLoc) {
FieldDecl *DirectMember = dyn_cast<FieldDecl>(Member);
IndirectFieldDecl *IndirectMember = dyn_cast<IndirectFieldDecl>(Member);
assert((DirectMember || IndirectMember) &&
"Member must be a FieldDecl or IndirectFieldDecl");
- if (Args.DiagnoseUnexpandedParameterPack(*this))
+ if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer))
return true;
if (Member->isInvalidDecl())
@@ -2120,13 +2120,19 @@
// foo(foo)
// where foo is not also a parameter to the constructor.
// TODO: implement -Wuninitialized and fold this into that framework.
- for (MultiInitializer::iterator I = Args.begin(), E = Args.end();
- I != E; ++I) {
+ Expr **Args;
+ unsigned NumArgs;
+ if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+ Args = ParenList->getExprs();
+ NumArgs = ParenList->getNumExprs();
+ } else {
+ InitListExpr *InitList = cast<InitListExpr>(Init);
+ Args = InitList->getInits();
+ NumArgs = InitList->getNumInits();
+ }
+ for (unsigned i = 0; i < NumArgs; ++i) {
SourceLocation L;
- Expr *Arg = *I;
- if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Arg))
- Arg = DIE->getInit();
- if (InitExprContainsUninitializedFields(Arg, Member, &L)) {
+ if (InitExprContainsUninitializedFields(Args[i], Member, &L)) {
// FIXME: Return true in the case when other fields are used before being
// uninitialized. For example, let this field be the i'th field. When
// initializing the i'th field, throw a warning if any of the >= i'th
@@ -2137,14 +2143,11 @@
}
}
- bool HasDependentArg = Args.isTypeDependent();
+ SourceRange InitRange = Init->getSourceRange();
- Expr *Init;
- if (Member->getType()->isDependentType() || HasDependentArg) {
+ if (Member->getType()->isDependentType() || Init->isTypeDependent()) {
// Can't check initialization for a member of dependent type or when
// any of the arguments are type-dependent expressions.
- Init = Args.CreateInitExpr(Context,Member->getType().getNonReferenceType());
-
DiscardCleanupsInEvaluationContext();
} else {
// Initialize the member.
@@ -2152,14 +2155,22 @@
DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0)
: InitializedEntity::InitializeMember(IndirectMember, 0);
InitializationKind Kind =
- InitializationKind::CreateDirect(IdLoc, Args.getStartLoc(),
- Args.getEndLoc());
+ InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
+ InitRange.getEnd());
- ExprResult MemberInit = Args.PerformInit(*this, MemberEntity, Kind);
+ if (isa<InitListExpr>(Init)) {
+ Args = &Init;
+ NumArgs = 1;
+ }
+ InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs);
+ ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind,
+ MultiExprArg(*this, Args, NumArgs),
+ 0);
if (MemberInit.isInvalid())
return true;
- CheckImplicitConversions(MemberInit.get(), Args.getStartLoc());
+ CheckImplicitConversions(MemberInit.get(),
+ InitRange.getBegin());
// C++0x [class.base.init]p7:
// The initialization of each base and member constitutes a
@@ -2170,14 +2181,13 @@
// If we are in a dependent context, template instantiation will
// perform this type-checking again. Just save the arguments that we
- // received in a ParenListExpr.
+ // received.
// FIXME: This isn't quite ideal, since our ASTs don't capture all
// of the information that we have about the member
// initializer. However, deconstructing the ASTs is a dicey process,
// and this approach is far more likely to get the corner cases right.
if (CurContext->isDependentContext()) {
- Init = Args.CreateInitExpr(Context,
- Member->getType().getNonReferenceType());
+ // The existing Init will do fine.
} else {
Init = MemberInit.get();
CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc);
@@ -2185,19 +2195,18 @@
}
if (DirectMember) {
- return new (Context) CXXCtorInitializer(Context, DirectMember,
- IdLoc, Args.getStartLoc(),
- Init, Args.getEndLoc());
+ return new (Context) CXXCtorInitializer(Context, DirectMember, IdLoc,
+ InitRange.getBegin(), Init,
+ InitRange.getEnd());
} else {
- return new (Context) CXXCtorInitializer(Context, IndirectMember,
- IdLoc, Args.getStartLoc(),
- Init, Args.getEndLoc());
+ return new (Context) CXXCtorInitializer(Context, IndirectMember, IdLoc,
+ InitRange.getBegin(), Init,
+ InitRange.getEnd());
}
}
MemInitResult
-Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo,
- const MultiInitializer &Args,
+Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
CXXRecordDecl *ClassDecl) {
SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin();
if (!LangOpts.CPlusPlus0x)
@@ -2205,21 +2214,31 @@
<< TInfo->getTypeLoc().getLocalSourceRange();
Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor);
+ SourceRange InitRange = Init->getSourceRange();
// Initialize the object.
InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation(
QualType(ClassDecl->getTypeForDecl(), 0));
InitializationKind Kind =
- InitializationKind::CreateDirect(NameLoc, Args.getStartLoc(),
- Args.getEndLoc());
+ InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
+ InitRange.getEnd());
- ExprResult DelegationInit = Args.PerformInit(*this, DelegationEntity, Kind);
+ Expr **Args = &Init;
+ unsigned NumArgs = 1;
+ if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+ Args = ParenList->getExprs();
+ NumArgs = ParenList->getNumExprs();
+ }
+ InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs);
+ ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind,
+ MultiExprArg(*this, Args,NumArgs),
+ 0);
if (DelegationInit.isInvalid())
return true;
assert(cast<CXXConstructExpr>(DelegationInit.get())->getConstructor() &&
"Delegating constructor with no target?");
- CheckImplicitConversions(DelegationInit.get(), Args.getStartLoc());
+ CheckImplicitConversions(DelegationInit.get(), InitRange.getBegin());
// C++0x [class.base.init]p7:
// The initialization of each base and member constitutes a
@@ -2228,18 +2247,15 @@
if (DelegationInit.isInvalid())
return true;
- return new (Context) CXXCtorInitializer(Context, TInfo, Args.getStartLoc(),
+ return new (Context) CXXCtorInitializer(Context, TInfo, InitRange.getBegin(),
DelegationInit.takeAs<Expr>(),
- Args.getEndLoc());
+ InitRange.getEnd());
}
MemInitResult
Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
- const MultiInitializer &Args,
- CXXRecordDecl *ClassDecl,
+ Expr *Init, CXXRecordDecl *ClassDecl,
SourceLocation EllipsisLoc) {
- bool HasDependentArg = Args.isTypeDependent();
-
SourceLocation BaseLoc
= BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin();
@@ -2253,13 +2269,14 @@
// of that class, the mem-initializer is ill-formed. A
// mem-initializer-list can initialize a base class using any
// name that denotes that base class type.
- bool Dependent = BaseType->isDependentType() || HasDependentArg;
+ bool Dependent = BaseType->isDependentType() || Init->isTypeDependent();
+ SourceRange InitRange = Init->getSourceRange();
if (EllipsisLoc.isValid()) {
// This is a pack expansion.
if (!BaseType->containsUnexpandedParameterPack()) {
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
- << SourceRange(BaseLoc, Args.getEndLoc());
+ << SourceRange(BaseLoc, InitRange.getEnd());
EllipsisLoc = SourceLocation();
}
@@ -2268,7 +2285,7 @@
if (DiagnoseUnexpandedParameterPack(BaseLoc, BaseTInfo, UPPC_Initializer))
return true;
- if (Args.DiagnoseUnexpandedParameterPack(*this))
+ if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer))
return true;
}
@@ -2278,7 +2295,7 @@
if (!Dependent) {
if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0),
BaseType))
- return BuildDelegatingInitializer(BaseTInfo, Args, ClassDecl);
+ return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl);
FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
VirtualBaseSpec);
@@ -2303,16 +2320,12 @@
}
if (Dependent) {
- // Can't check initialization for a base of dependent type or when
- // any of the arguments are type-dependent expressions.
- Expr *BaseInit = Args.CreateInitExpr(Context, BaseType);
-
DiscardCleanupsInEvaluationContext();
return new (Context) CXXCtorInitializer(Context, BaseTInfo,
/*IsVirtual=*/false,
- Args.getStartLoc(), BaseInit,
- Args.getEndLoc(), EllipsisLoc);
+ InitRange.getBegin(), Init,
+ InitRange.getEnd(), EllipsisLoc);
}
// C++ [base.class.init]p2:
@@ -2323,8 +2336,7 @@
return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
<< BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
- CXXBaseSpecifier *BaseSpec
- = const_cast<CXXBaseSpecifier *>(DirectBaseSpec);
+ CXXBaseSpecifier *BaseSpec = const_cast<CXXBaseSpecifier *>(DirectBaseSpec);
if (!BaseSpec)
BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec);
@@ -2332,14 +2344,23 @@
InitializedEntity BaseEntity =
InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec);
InitializationKind Kind =
- InitializationKind::CreateDirect(BaseLoc, Args.getStartLoc(),
- Args.getEndLoc());
+ InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(),
+ InitRange.getEnd());
- ExprResult BaseInit = Args.PerformInit(*this, BaseEntity, Kind);
+ Expr **Args = &Init;
+ unsigned NumArgs = 1;
+ if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+ Args = ParenList->getExprs();
+ NumArgs = ParenList->getNumExprs();
+ }
+ InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs);
+ ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind,
+ MultiExprArg(*this, Args, NumArgs),
+ 0);
if (BaseInit.isInvalid())
return true;
- CheckImplicitConversions(BaseInit.get(), Args.getStartLoc());
+ CheckImplicitConversions(BaseInit.get(), InitRange.getBegin());
// C++0x [class.base.init]p7:
// The initialization of each base and member constitutes a
@@ -2356,13 +2377,13 @@
// initializer. However, deconstructing the ASTs is a dicey process,
// and this approach is far more likely to get the corner cases right.
if (CurContext->isDependentContext())
- BaseInit = Owned(Args.CreateInitExpr(Context, BaseType));
+ BaseInit = Owned(Init);
return new (Context) CXXCtorInitializer(Context, BaseTInfo,
BaseSpec->isVirtual(),
- Args.getStartLoc(),
+ InitRange.getBegin(),
BaseInit.takeAs<Expr>(),
- Args.getEndLoc(), EllipsisLoc);
+ InitRange.getEnd(), EllipsisLoc);
}
// Create a static_cast\<T&&>(expr).
@@ -9064,7 +9085,8 @@
MarkFunctionReferenced(ConstructLoc, Constructor);
return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
Constructor, Elidable, Exprs, NumExprs,
- HadMultipleCandidates, RequiresZeroInit,
+ HadMultipleCandidates, /*FIXME*/false,
+ RequiresZeroInit,
static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind),
ParenRange));
}
@@ -9116,187 +9138,6 @@
Diag(VD->getLocation(), diag::warn_global_destructor);
}
-/// AddCXXDirectInitializerToDecl - This action is called immediately after
-/// ActOnDeclarator, when a C++ direct initializer is present.
-/// e.g: "int x(1);"
-void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl,
- SourceLocation LParenLoc,
- MultiExprArg Exprs,
- SourceLocation RParenLoc,
- bool TypeMayContainAuto) {
- // If there is no declaration, there was an error parsing it. Just ignore
- // the initializer.
- if (RealDecl == 0)
- return;
-
- VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl);
- if (!VDecl) {
- Diag(RealDecl->getLocation(), diag::err_illegal_initializer);
- RealDecl->setInvalidDecl();
- return;
- }
-
- // C++0x [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for.
- if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
- if (Exprs.size() == 0) {
- // It isn't possible to write this directly, but it is possible to
- // end up in this situation with "auto x(some_pack...);"
- Diag(LParenLoc, diag::err_auto_var_init_no_expression)
- << VDecl->getDeclName() << VDecl->getType()
- << VDecl->getSourceRange();
- RealDecl->setInvalidDecl();
- return;
- }
-
- if (Exprs.size() > 1) {
- Diag(Exprs.get()[1]->getSourceRange().getBegin(),
- diag::err_auto_var_init_multiple_expressions)
- << VDecl->getDeclName() << VDecl->getType()
- << VDecl->getSourceRange();
- RealDecl->setInvalidDecl();
- return;
- }
-
- Expr *Init = Exprs.get()[0];
- TypeSourceInfo *DeducedType = 0;
- if (DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType) ==
- DAR_Failed)
- DiagnoseAutoDeductionFailure(VDecl, Init);
- if (!DeducedType) {
- RealDecl->setInvalidDecl();
- return;
- }
- VDecl->setTypeSourceInfo(DeducedType);
- VDecl->setType(DeducedType->getType());
-
- // In ARC, infer lifetime.
- if (getLangOptions().ObjCAutoRefCount && inferObjCARCLifetime(VDecl))
- VDecl->setInvalidDecl();
-
- // If this is a redeclaration, check that the type we just deduced matches
- // the previously declared type.
- if (VarDecl *Old = VDecl->getPreviousDecl())
- MergeVarDeclTypes(VDecl, Old);
- }
-
- // We will represent direct-initialization similarly to copy-initialization:
- // int x(1); -as-> int x = 1;
- // ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c);
- //
- // Clients that want to distinguish between the two forms, can check for
- // direct initializer using VarDecl::hasCXXDirectInitializer().
- // A major benefit is that clients that don't particularly care about which
- // exactly form was it (like the CodeGen) can handle both cases without
- // special case code.
-
- // C++ 8.5p11:
- // The form of initialization (using parentheses or '=') is generally
- // insignificant, but does matter when the entity being initialized has a
- // class type.
-
- if (!VDecl->getType()->isDependentType() &&
- !VDecl->getType()->isIncompleteArrayType() &&
- RequireCompleteType(VDecl->getLocation(), VDecl->getType(),
- diag::err_typecheck_decl_incomplete_type)) {
- VDecl->setInvalidDecl();
- return;
- }
-
- // The variable can not have an abstract class type.
- if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(),
- diag::err_abstract_type_in_decl,
- AbstractVariableType))
- VDecl->setInvalidDecl();
-
- const VarDecl *Def;
- if ((Def = VDecl->getDefinition()) && Def != VDecl) {
- Diag(VDecl->getLocation(), diag::err_redefinition)
- << VDecl->getDeclName();
- Diag(Def->getLocation(), diag::note_previous_definition);
- VDecl->setInvalidDecl();
- return;
- }
-
- // C++ [class.static.data]p4
- // If a static data member is of const integral or const
- // enumeration type, its declaration in the class definition can
- // specify a constant-initializer which shall be an integral
- // constant expression (5.19). In that case, the member can appear
- // in integral constant expressions. The member shall still be
- // defined in a namespace scope if it is used in the program and the
- // namespace scope definition shall not contain an initializer.
- //
- // We already performed a redefinition check above, but for static
- // data members we also need to check whether there was an in-class
- // declaration with an initializer.
- const VarDecl* PrevInit = 0;
- if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) {
- Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName();
- Diag(PrevInit->getLocation(), diag::note_previous_definition);
- return;
- }
-
- if (VDecl->hasLocalStorage())
- getCurFunction()->setHasBranchProtectedScope();
-
- bool IsDependent = false;
- for (unsigned I = 0, N = Exprs.size(); I != N; ++I) {
- if (DiagnoseUnexpandedParameterPack(Exprs.get()[I], UPPC_Expression)) {
- VDecl->setInvalidDecl();
- return;
- }
-
- if (Exprs.get()[I]->isTypeDependent())
- IsDependent = true;
- }
-
- // If either the declaration has a dependent type or if any of the
- // expressions is type-dependent, we represent the initialization
- // via a ParenListExpr for later use during template instantiation.
- if (VDecl->getType()->isDependentType() || IsDependent) {
- // Let clients know that initialization was done with a direct initializer.
- VDecl->setCXXDirectInitializer(true);
-
- // Store the initialization expressions as a ParenListExpr.
- unsigned NumExprs = Exprs.size();
- VDecl->setInit(new (Context) ParenListExpr(
- Context, LParenLoc, (Expr **)Exprs.release(), NumExprs, RParenLoc,
- VDecl->getType().getNonReferenceType()));
- return;
- }
-
- // Capture the variable that is being initialized and the style of
- // initialization.
- InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
-
- // FIXME: Poor source location information.
- InitializationKind Kind
- = InitializationKind::CreateDirect(VDecl->getLocation(),
- LParenLoc, RParenLoc);
-
- QualType T = VDecl->getType();
- InitializationSequence InitSeq(*this, Entity, Kind,
- Exprs.get(), Exprs.size());
- ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(Exprs), &T);
- if (Result.isInvalid()) {
- VDecl->setInvalidDecl();
- return;
- } else if (T != VDecl->getType()) {
- VDecl->setType(T);
- Result.get()->setType(T);
- }
-
-
- Expr *Init = Result.get();
- CheckImplicitConversions(Init, LParenLoc);
-
- Init = MaybeCreateExprWithCleanups(Init);
- VDecl->setInit(Init);
- VDecl->setCXXDirectInitializer(true);
-
- CheckCompleteVariableDeclaration(VDecl);
-}
-
/// \brief Given a constructor and the set of arguments provided for the
/// constructor, convert the arguments and add any required default arguments
/// to form a proper call to this constructor.
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sat Feb 11 17:51:47 2012
@@ -2920,6 +2920,11 @@
case tok::minusminus: Opc = UO_PostDec; break;
}
+ // Since this might is a postfix expression, get rid of ParenListExprs.
+ ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Input);
+ if (Result.isInvalid()) return ExprError();
+ Input = Result.take();
+
return BuildUnaryOp(S, OpLoc, Opc, Input);
}
@@ -4251,8 +4256,8 @@
return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, initE);
}
-/// This is not an AltiVec-style cast, so turn the ParenListExpr into a sequence
-/// of comma binary operators.
+/// This is not an AltiVec-style cast or or C++ direct-initialization, so turn
+/// the ParenListExpr into a sequence of comma binary operators.
ExprResult
Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) {
ParenListExpr *E = dyn_cast<ParenListExpr>(OrigExpr);
@@ -4270,18 +4275,13 @@
return ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), Result.get());
}
-ExprResult Sema::ActOnParenOrParenListExpr(SourceLocation L,
- SourceLocation R,
- MultiExprArg Val) {
+ExprResult Sema::ActOnParenListExpr(SourceLocation L,
+ SourceLocation R,
+ MultiExprArg Val) {
unsigned nexprs = Val.size();
Expr **exprs = reinterpret_cast<Expr**>(Val.release());
assert((exprs != 0) && "ActOnParenOrParenListExpr() missing expr list");
- Expr *expr;
- if (nexprs == 1)
- expr = new (Context) ParenExpr(L, R, exprs[0]);
- else
- expr = new (Context) ParenListExpr(Context, L, exprs, nexprs, R,
- exprs[nexprs-1]->getType());
+ Expr *expr = new (Context) ParenListExpr(Context, L, exprs, nexprs, R);
return Owned(expr);
}
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sat Feb 11 17:51:47 2012
@@ -4708,6 +4708,13 @@
}
}
+ if (Kind.getKind() == InitializationKind::IK_Direct &&
+ !Kind.isExplicitCast()) {
+ // Rebuild the ParenListExpr.
+ SourceRange ParenRange = Kind.getParenRange();
+ return S.ActOnParenListExpr(ParenRange.getBegin(), ParenRange.getEnd(),
+ move(Args));
+ }
assert(Kind.getKind() == InitializationKind::IK_Copy ||
Kind.isExplicitCast());
return ExprResult(Args.release()[0]);
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Sat Feb 11 17:51:47 2012
@@ -1833,14 +1833,16 @@
FieldDecl *NewField = FieldsWithMemberInitializers[I].second;
Expr *OldInit = OldField->getInClassInitializer();
- SourceLocation LParenLoc, RParenLoc;
- ASTOwningVector<Expr*> NewArgs(*this);
- if (InstantiateInitializer(OldInit, TemplateArgs, LParenLoc, NewArgs,
- RParenLoc))
+ ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
+ /*CXXDirectInit=*/false);
+ if (NewInit.isInvalid())
NewField->setInvalidDecl();
else {
- assert(NewArgs.size() == 1 && "wrong number of in-class initializers");
- ActOnCXXInClassMemberInitializer(NewField, LParenLoc, NewArgs[0]);
+ Expr *Init = NewInit.take();
+ assert(Init && "no-argument initializer in class");
+ assert(!isa<ParenListExpr>(Init) && "call-style init in class");
+ ActOnCXXInClassMemberInitializer(NewField,
+ Init->getSourceRange().getBegin(), Init);
}
}
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sat Feb 11 17:51:47 2012
@@ -252,66 +252,6 @@
return Inst;
}
-/// \brief Instantiate an initializer, breaking it into separate
-/// initialization arguments.
-///
-/// \param Init The initializer to instantiate.
-///
-/// \param TemplateArgs Template arguments to be substituted into the
-/// initializer.
-///
-/// \param NewArgs Will be filled in with the instantiation arguments.
-///
-/// \returns true if an error occurred, false otherwise
-bool Sema::InstantiateInitializer(Expr *Init,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- SourceLocation &LParenLoc,
- ASTOwningVector<Expr*> &NewArgs,
- SourceLocation &RParenLoc) {
- NewArgs.clear();
- LParenLoc = SourceLocation();
- RParenLoc = SourceLocation();
-
- if (!Init)
- return false;
-
- if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
- Init = ExprTemp->getSubExpr();
-
- while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init))
- Init = Binder->getSubExpr();
-
- if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init))
- Init = ICE->getSubExprAsWritten();
-
- if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
- LParenLoc = ParenList->getLParenLoc();
- RParenLoc = ParenList->getRParenLoc();
- return SubstExprs(ParenList->getExprs(), ParenList->getNumExprs(),
- true, TemplateArgs, NewArgs);
- }
-
- if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) {
- if (!isa<CXXTemporaryObjectExpr>(Construct)) {
- if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true,
- TemplateArgs, NewArgs))
- return true;
-
- // FIXME: Fake locations!
- LParenLoc = PP.getLocForEndOfToken(Init->getLocStart());
- RParenLoc = LParenLoc;
- return false;
- }
- }
-
- ExprResult Result = SubstExpr(Init, TemplateArgs);
- if (Result.isInvalid())
- return true;
-
- NewArgs.push_back(Result.takeAs<Expr>());
- return false;
-}
-
Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
// If this is the variable for an anonymous struct or union,
// instantiate the anonymous struct/union type first.
@@ -342,7 +282,7 @@
D->getStorageClass(),
D->getStorageClassAsWritten());
Var->setThreadSpecified(D->isThreadSpecified());
- Var->setCXXDirectInitializer(D->hasCXXDirectInitializer());
+ Var->setInitStyle(D->getInitStyle());
Var->setCXXForRangeDecl(D->isCXXForRangeDecl());
Var->setConstexpr(D->isConstexpr());
@@ -403,25 +343,16 @@
SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
// Instantiate the initializer.
- SourceLocation LParenLoc, RParenLoc;
- ASTOwningVector<Expr*> InitArgs(SemaRef);
- if (!SemaRef.InstantiateInitializer(D->getInit(), TemplateArgs, LParenLoc,
- InitArgs, RParenLoc)) {
+ ExprResult Init = SemaRef.SubstInitializer(D->getInit(), TemplateArgs,
+ D->getInitStyle() == VarDecl::CallInit);
+ if (!Init.isInvalid()) {
bool TypeMayContainAuto = true;
- if (D->hasCXXDirectInitializer()) {
- // Add the direct initializer to the declaration.
- SemaRef.AddCXXDirectInitializerToDecl(Var,
- LParenLoc,
- move_arg(InitArgs),
- RParenLoc,
- TypeMayContainAuto);
- } else if (InitArgs.size() == 0) {
+ if (Init.get()) {
+ bool DirectInit = D->isDirectInit();
+ SemaRef.AddInitializerToDecl(Var, Init.take(), DirectInit,
+ TypeMayContainAuto);
+ } else
SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto);
- } else {
- assert(InitArgs.size() == 1);
- Expr *Init = InitArgs.take()[0];
- SemaRef.AddInitializerToDecl(Var, Init, false, TypeMayContainAuto);
- }
} else {
// FIXME: Not too happy about invalidating the declaration
// because of a bogus initializer.
@@ -2743,18 +2674,6 @@
}
}
-static MultiInitializer CreateMultiInitializer(SmallVectorImpl<Expr*> &Args,
- const CXXCtorInitializer *Init) {
- // FIXME: This is a hack that will do slightly the wrong thing for an
- // initializer of the form foo({...}).
- // The right thing to do would be to modify InstantiateInitializer to create
- // the MultiInitializer.
- if (Args.size() == 1 && isa<InitListExpr>(Args[0]))
- return MultiInitializer(Args[0]);
- return MultiInitializer(Init->getLParenLoc(), Args.data(),
- Args.size(), Init->getRParenLoc());
-}
-
void
Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
const CXXConstructorDecl *Tmpl,
@@ -2774,9 +2693,6 @@
if (!Init->isWritten())
continue;
- SourceLocation LParenLoc, RParenLoc;
- ASTOwningVector<Expr*> NewArgs(*this);
-
SourceLocation EllipsisLoc;
if (Init->isPackExpansion()) {
@@ -2804,8 +2720,9 @@
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
// Instantiate the initializer.
- if (InstantiateInitializer(Init->getInit(), TemplateArgs,
- LParenLoc, NewArgs, RParenLoc)) {
+ ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs,
+ /*CXXDirectInit=*/true);
+ if (TempInit.isInvalid()) {
AnyErrors = true;
break;
}
@@ -2821,9 +2738,8 @@
}
// Build the initializer.
- MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init));
MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(),
- BaseTInfo, MultiInit,
+ BaseTInfo, TempInit.take(),
New->getParent(),
SourceLocation());
if (NewInit.isInvalid()) {
@@ -2832,15 +2748,15 @@
}
NewInits.push_back(NewInit.get());
- NewArgs.clear();
}
continue;
}
// Instantiate the initializer.
- if (InstantiateInitializer(Init->getInit(), TemplateArgs,
- LParenLoc, NewArgs, RParenLoc)) {
+ ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs,
+ /*CXXDirectInit=*/true);
+ if (TempInit.isInvalid()) {
AnyErrors = true;
continue;
}
@@ -2857,13 +2773,11 @@
continue;
}
- MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init));
-
if (Init->isBaseInitializer())
- NewInit = BuildBaseInitializer(TInfo->getType(), TInfo, MultiInit,
+ NewInit = BuildBaseInitializer(TInfo->getType(), TInfo, TempInit.take(),
New->getParent(), EllipsisLoc);
else
- NewInit = BuildDelegatingInitializer(TInfo, MultiInit,
+ NewInit = BuildDelegatingInitializer(TInfo, TempInit.take(),
cast<CXXRecordDecl>(CurContext->getParent()));
} else if (Init->isMemberInitializer()) {
FieldDecl *Member = cast_or_null<FieldDecl>(FindInstantiatedDecl(
@@ -2876,8 +2790,7 @@
continue;
}
- MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init));
- NewInit = BuildMemberInitializer(Member, MultiInit,
+ NewInit = BuildMemberInitializer(Member, TempInit.take(),
Init->getSourceLocation());
} else if (Init->isIndirectMemberInitializer()) {
IndirectFieldDecl *IndirectMember =
@@ -2891,8 +2804,7 @@
continue;
}
- MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init));
- NewInit = BuildMemberInitializer(IndirectMember, MultiInit,
+ NewInit = BuildMemberInitializer(IndirectMember, TempInit.take(),
Init->getSourceLocation());
}
@@ -2900,9 +2812,6 @@
AnyErrors = true;
New->setInvalidDecl();
} else {
- // FIXME: It would be nice if ASTOwningVector had a release function.
- NewArgs.take();
-
NewInits.push_back(NewInit.get());
}
}
@@ -2915,6 +2824,45 @@
AnyErrors);
}
+ExprResult Sema::SubstInitializer(Expr *Init,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool CXXDirectInit) {
+ // Initializers are instantiated like expressions, except that various outer
+ // layers are stripped.
+ if (!Init)
+ return Owned(Init);
+
+ if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
+ Init = ExprTemp->getSubExpr();
+
+ while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init))
+ Init = Binder->getSubExpr();
+
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init))
+ Init = ICE->getSubExprAsWritten();
+
+ // If this is a direct-initializer, we take apart CXXConstructExprs.
+ // Everything else is passed through.
+ CXXConstructExpr *Construct;
+ if (!CXXDirectInit || !(Construct = dyn_cast<CXXConstructExpr>(Init)) ||
+ isa<CXXTemporaryObjectExpr>(Construct))
+ return SubstExpr(Init, TemplateArgs);
+
+ ASTOwningVector<Expr*> NewArgs(*this);
+ if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true,
+ TemplateArgs, NewArgs))
+ return ExprError();
+
+ // Treat an empty initializer like none.
+ if (NewArgs.empty())
+ return Owned((Expr*)0);
+
+ // Build a ParenListExpr to represent anything else.
+ // FIXME: Fake locations!
+ SourceLocation Loc = PP.getLocForEndOfToken(Init->getLocStart());
+ return ActOnParenListExpr(Loc, Loc, move_arg(NewArgs));
+}
+
// TODO: this could be templated if the various decl types used the
// same method name.
static bool isInstantiationOf(ClassTemplateDecl *Pattern,
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Sat Feb 11 17:51:47 2012
@@ -1646,10 +1646,9 @@
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildParenListExpr(SourceLocation LParenLoc,
- MultiExprArg SubExprs,
- SourceLocation RParenLoc) {
- return getSema().ActOnParenOrParenListExpr(LParenLoc, RParenLoc,
- move(SubExprs));
+ MultiExprArg SubExprs,
+ SourceLocation RParenLoc) {
+ return getSema().ActOnParenListExpr(LParenLoc, RParenLoc, move(SubExprs));
}
/// \brief Build a new address-of-label expression.
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Sat Feb 11 17:51:47 2012
@@ -877,7 +877,7 @@
VD->VarDeclBits.SClass = (StorageClass)Record[Idx++];
VD->VarDeclBits.SClassAsWritten = (StorageClass)Record[Idx++];
VD->VarDeclBits.ThreadSpecified = Record[Idx++];
- VD->VarDeclBits.HasCXXDirectInit = Record[Idx++];
+ VD->VarDeclBits.InitStyle = Record[Idx++];
VD->VarDeclBits.ExceptionVar = Record[Idx++];
VD->VarDeclBits.NRVOVariable = Record[Idx++];
VD->VarDeclBits.CXXForRangeDecl = Record[Idx++];
Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Sat Feb 11 17:51:47 2012
@@ -656,7 +656,7 @@
Record.push_back(D->getStorageClass()); // FIXME: stable encoding
Record.push_back(D->getStorageClassAsWritten());
Record.push_back(D->isThreadSpecified());
- Record.push_back(D->hasCXXDirectInitializer());
+ Record.push_back(D->getInitStyle());
Record.push_back(D->isExceptionVariable());
Record.push_back(D->isNRVOVariable());
Record.push_back(D->isCXXForRangeDecl());
@@ -688,7 +688,7 @@
D->getDeclName().getNameKind() == DeclarationName::Identifier &&
!D->hasExtInfo() &&
D->getFirstDeclaration() == D->getMostRecentDecl() &&
- !D->hasCXXDirectInitializer() &&
+ D->getInitStyle() == VarDecl::CInit &&
D->getInit() == 0 &&
!isa<ParmVarDecl>(D) &&
!SpecInfo)
@@ -728,7 +728,7 @@
D->getAccess() == AS_none &&
!D->isModulePrivate() &&
D->getStorageClass() == 0 &&
- !D->hasCXXDirectInitializer() && // Can params have this ever?
+ D->getInitStyle() == VarDecl::CInit && // Can params have anything else?
D->getFunctionScopeDepth() == 0 &&
D->getObjCDeclQualifier() == 0 &&
!D->isKNRPromoted() &&
Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp?rev=150318&r1=150317&r2=150318&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp Sat Feb 11 17:51:47 2012
@@ -185,7 +185,7 @@
void test_initializers() {
T copy_init = static_cast<Types>(0); // expected-error{{initializer contains unexpanded parameter pack 'Types'}}
- T direct_init(0, static_cast<Types>(0)); // expected-error{{expression contains unexpanded parameter pack 'Types'}}
+ T direct_init(0, static_cast<Types>(0)); // expected-error{{initializer contains unexpanded parameter pack 'Types'}}
T list_init = { static_cast<Types>(0) }; // expected-error{{initializer contains unexpanded parameter pack 'Types'}}
}
Removed: cfe/trunk/test/Sema/paren-list-expr-type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/paren-list-expr-type.cpp?rev=150317&view=auto
==============================================================================
--- cfe/trunk/test/Sema/paren-list-expr-type.cpp (original)
+++ cfe/trunk/test/Sema/paren-list-expr-type.cpp (removed)
@@ -1,17 +0,0 @@
-// RUN: %clang -cc1 -ast-dump %s | not grep NULL
-// Makes sure that we don't introduce null types when handling
-// ParenListExpr.
-
-template<typename T> class X { void f() { X x(*this); } };
-
-template<typename T> class Y { Y() : t(1) {} T t; };
-
-template<typename T> class Z { Z() : b(true) {} const bool b; };
-
-template<typename T> class A : public Z<T> { A() : Z<T>() {} };
-
-class C {};
-template<typename T> class D : public C { D(): C() {} };
-
-void f() { (int)(1, 2); }
-
Added: cfe/trunk/test/SemaTemplate/nested-incomplete-class.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/nested-incomplete-class.cpp?rev=150318&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/nested-incomplete-class.cpp (added)
+++ cfe/trunk/test/SemaTemplate/nested-incomplete-class.cpp Sat Feb 11 17:51:47 2012
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -fsyntax-only %s
+
+template <typename T>
+struct foo {
+ struct bar;
+
+ bar fn() {
+ // Should not get errors about bar being incomplete here.
+ bar b = bar(1, 2);
+ return b;
+ }
+};
+
+template <typename T>
+struct foo<T>::bar {
+ bar(int, int);
+};
+
+void fn() {
+ foo<int>().fn();
+}
More information about the cfe-commits
mailing list