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. llvm-svn: 150318
This commit is contained in:
parent
46afb55177
commit
a935179ab7
|
@ -681,6 +681,13 @@ public:
|
|||
/// 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 @@ private:
|
|||
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 @@ private:
|
|||
/// \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 @@ protected:
|
|||
/// 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 @@ public:
|
|||
/// 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
|
||||
|
|
|
@ -3977,7 +3977,7 @@ class ParenListExpr : public Expr {
|
|||
|
||||
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) { }
|
||||
|
|
|
@ -812,6 +812,7 @@ private:
|
|||
unsigned NumArgs : 16;
|
||||
bool Elidable : 1;
|
||||
bool HadMultipleCandidates : 1;
|
||||
bool ListInitialization : 1;
|
||||
bool ZeroInitialization : 1;
|
||||
unsigned ConstructKind : 2;
|
||||
Stmt **Args;
|
||||
|
@ -822,32 +823,36 @@ protected:
|
|||
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 @@ public:
|
|||
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; }
|
||||
|
|
|
@ -326,20 +326,22 @@ class InitializationKind {
|
|||
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 @@ public:
|
|||
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) {
|
||||
|
|
|
@ -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
|
|
@ -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 @@ public:
|
|||
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 @@ public:
|
|||
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 @@ public:
|
|||
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 @@ public:
|
|||
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 @@ public:
|
|||
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);
|
||||
|
|
|
@ -621,16 +621,20 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
|
|||
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 << " = ";
|
||||
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 << ")";
|
||||
}
|
||||
Init->printPretty(Out, Context, 0, Policy, Indentation);
|
||||
if (D->hasCXXDirectInitializer())
|
||||
Out << ")";
|
||||
}
|
||||
prettyPrintAttributes(D);
|
||||
}
|
||||
|
|
|
@ -461,7 +461,13 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
|
|||
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.
|
||||
}
|
||||
|
|
|
@ -3414,11 +3414,10 @@ void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx,
|
|||
|
||||
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())
|
||||
|
|
|
@ -653,7 +653,7 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C,
|
|||
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 @@ CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T,
|
|||
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 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
|
|||
CXXConstructorDecl *D, bool elidable,
|
||||
Expr **args, unsigned numargs,
|
||||
bool HadMultipleCandidates,
|
||||
bool ListInitialization,
|
||||
bool ZeroInitialization,
|
||||
ConstructionKind ConstructKind,
|
||||
SourceRange ParenRange)
|
||||
|
@ -691,6 +694,7 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
|
|||
T->containsUnexpandedParameterPack()),
|
||||
Constructor(D), Loc(Loc), ParenRange(ParenRange), NumArgs(numargs),
|
||||
Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates),
|
||||
ListInitialization(ListInitialization),
|
||||
ZeroInitialization(ZeroInitialization),
|
||||
ConstructKind(ConstructKind), Args(0)
|
||||
{
|
||||
|
|
|
@ -2740,7 +2740,8 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
|
|||
CXXConstExpr->getConstructor(),
|
||||
CXXConstExpr->isElidable(),
|
||||
&ConstructorArgs[0], ConstructorArgs.size(),
|
||||
CXXConstExpr->hadMultipleCandidates(),
|
||||
CXXConstExpr->hadMultipleCandidates(),
|
||||
CXXConstExpr->isListInitialization(),
|
||||
CXXConstExpr->requiresZeroInitialization(),
|
||||
CXXConstExpr->getConstructionKind(), SourceRange());
|
||||
|
||||
|
|
|
@ -1344,10 +1344,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
|
|||
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.
|
||||
|
|
|
@ -2006,8 +2006,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
|
|||
|
||||
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);
|
||||
|
|
|
@ -8,7 +8,6 @@ add_clang_library(clangSema
|
|||
DelayedDiagnostic.cpp
|
||||
IdentifierResolver.cpp
|
||||
JumpDiagnostics.cpp
|
||||
MultiInitializer.cpp
|
||||
Scope.cpp
|
||||
Sema.cpp
|
||||
SemaAccess.cpp
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -2139,9 +2139,8 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
|
|||
/// 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 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
|
|||
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 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
|
|||
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 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
|
|||
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 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
|
|||
: 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 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
|
|||
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 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -1768,7 +1768,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
|
|||
Expr *InitList,
|
||||
SourceLocation EllipsisLoc) {
|
||||
return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
|
||||
DS, IdLoc, MultiInitializer(InitList),
|
||||
DS, IdLoc, InitList,
|
||||
EllipsisLoc);
|
||||
}
|
||||
|
||||
|
@ -1785,10 +1785,10 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
|
|||
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 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
|
|||
ParsedType TemplateTypeTy,
|
||||
const DeclSpec &DS,
|
||||
SourceLocation IdLoc,
|
||||
const MultiInitializer &Args,
|
||||
Expr *Init,
|
||||
SourceLocation EllipsisLoc) {
|
||||
if (!ConstructorD)
|
||||
return true;
|
||||
|
@ -1864,9 +1864,10 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
|
|||
(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 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
|
|||
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 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
|
|||
|
||||
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 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
|
|||
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 @@ static bool InitExprContainsUninitializedFields(const Stmt *S,
|
|||
}
|
||||
|
||||
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 @@ Sema::BuildMemberInitializer(ValueDecl *Member,
|
|||
// 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 @@ Sema::BuildMemberInitializer(ValueDecl *Member,
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ Sema::BuildMemberInitializer(ValueDecl *Member,
|
|||
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 @@ Sema::BuildMemberInitializer(ValueDecl *Member,
|
|||
|
||||
// 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 @@ Sema::BuildMemberInitializer(ValueDecl *Member,
|
|||
}
|
||||
|
||||
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 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo,
|
|||
<< 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 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo,
|
|||
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 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
|
|||
// 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 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
|
|||
if (DiagnoseUnexpandedParameterPack(BaseLoc, BaseTInfo, UPPC_Initializer))
|
||||
return true;
|
||||
|
||||
if (Args.DiagnoseUnexpandedParameterPack(*this))
|
||||
if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2278,7 +2295,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
|
|||
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 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
|
|||
}
|
||||
|
||||
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 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
|
|||
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 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
|
|||
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 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
|
|||
// 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 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
|
|||
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 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
|
|||
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.
|
||||
|
|
|
@ -2920,6 +2920,11 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
|
|||
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 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc,
|
|||
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 @@ Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) {
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -4708,6 +4708,13 @@ InitializationSequence::Perform(Sema &S,
|
|||
|
||||
}
|
||||
}
|
||||
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]);
|
||||
|
|
|
@ -1833,14 +1833,16 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -252,66 +252,6 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
|
|||
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 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
|
|||
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 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
|
|||
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 @@ void Sema::InstantiateStaticDataMemberDefinition(
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
|
|||
if (!Init->isWritten())
|
||||
continue;
|
||||
|
||||
SourceLocation LParenLoc, RParenLoc;
|
||||
ASTOwningVector<Expr*> NewArgs(*this);
|
||||
|
||||
SourceLocation EllipsisLoc;
|
||||
|
||||
if (Init->isPackExpansion()) {
|
||||
|
@ -2804,8 +2720,9 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
|
|||
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 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
|
|||
}
|
||||
|
||||
// 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 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
|
|||
}
|
||||
|
||||
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 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
|
|||
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 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
|
|||
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 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
|
|||
continue;
|
||||
}
|
||||
|
||||
MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init));
|
||||
NewInit = BuildMemberInitializer(IndirectMember, MultiInit,
|
||||
NewInit = BuildMemberInitializer(IndirectMember, TempInit.take(),
|
||||
Init->getSourceLocation());
|
||||
}
|
||||
|
||||
|
@ -2900,9 +2812,6 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
|
|||
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 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
|
|||
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,
|
||||
|
|
|
@ -1646,10 +1646,9 @@ public:
|
|||
/// 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.
|
||||
|
|
|
@ -877,7 +877,7 @@ void ASTDeclReader::VisitVarDecl(VarDecl *VD) {
|
|||
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++];
|
||||
|
|
|
@ -656,7 +656,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
|
|||
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 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
|
|||
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 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
|
|||
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() &&
|
||||
|
|
|
@ -185,7 +185,7 @@ struct alignas(Types) TestUnexpandedDecls : T{ // expected-error{{expression con
|
|||
|
||||
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'}}
|
||||
}
|
||||
|
||||
|
|
|
@ -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); }
|
||||
|
|
@ -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();
|
||||
}
|
Loading…
Reference in New Issue