Handle new by passing the Declaration to the Action, not a processed type.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60413 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index c0f2985..1bf07c4 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -80,30 +80,32 @@
// CXXNewExpr
CXXNewExpr::CXXNewExpr(bool globalNew, FunctionDecl *operatorNew,
Expr **placementArgs, unsigned numPlaceArgs,
- bool parenTypeId, QualType alloc,
+ bool parenTypeId, Expr *arraySize,
CXXConstructorDecl *constructor, bool initializer,
Expr **constructorArgs, unsigned numConsArgs,
FunctionDecl *operatorDelete, QualType ty,
SourceLocation startLoc, SourceLocation endLoc)
: Expr(CXXNewExprClass, ty), GlobalNew(globalNew), ParenTypeId(parenTypeId),
- Initializer(initializer), NumPlacementArgs(numPlaceArgs),
+ Initializer(initializer), Array(arraySize), NumPlacementArgs(numPlaceArgs),
NumConstructorArgs(numConsArgs), OperatorNew(operatorNew),
- OperatorDelete(operatorDelete), Constructor(constructor), AllocType(alloc),
+ OperatorDelete(operatorDelete), Constructor(constructor),
StartLoc(startLoc), EndLoc(endLoc)
{
- unsigned TotalSize = NumPlacementArgs + NumConstructorArgs;
+ unsigned TotalSize = Array + NumPlacementArgs + NumConstructorArgs;
SubExprs = new Stmt*[TotalSize];
unsigned i = 0;
- for(unsigned j = 0; j < NumPlacementArgs; ++j)
+ if (Array)
+ SubExprs[i++] = arraySize;
+ for (unsigned j = 0; j < NumPlacementArgs; ++j)
SubExprs[i++] = placementArgs[j];
- for(unsigned j = 0; j < NumConstructorArgs; ++j)
+ for (unsigned j = 0; j < NumConstructorArgs; ++j)
SubExprs[i++] = constructorArgs[j];
assert(i == TotalSize);
}
Stmt::child_iterator CXXNewExpr::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator CXXNewExpr::child_end() {
- return &SubExprs[0] + getNumPlacementArgs() + getNumConstructorArgs();
+ return &SubExprs[0] + Array + getNumPlacementArgs() + getNumConstructorArgs();
}
// CXXDeleteExpr
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index b6f0707..445e3e4 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -953,6 +953,9 @@
}
if (E->isParenTypeId())
OS << "(";
+ // FIXME: This doesn't print the dynamic array size. We'd have to split up
+ // the allocated type to correctly emit that, but without an ASTContext,
+ // that's not possible.
OS << E->getAllocatedType().getAsString();
if (E->isParenTypeId())
OS << ")";
diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp
index 40f5b3f..a860224 100644
--- a/lib/AST/StmtSerialization.cpp
+++ b/lib/AST/StmtSerialization.cpp
@@ -1444,7 +1444,10 @@
void CXXNewExpr::EmitImpl(Serializer& S) const {
S.Emit(getType());
- S.Emit(Initializer);
+ S.EmitBool(GlobalNew);
+ S.EmitBool(ParenTypeId);
+ S.EmitBool(Initializer);
+ S.EmitBool(Array);
S.EmitInt(NumPlacementArgs);
S.EmitInt(NumConstructorArgs);
S.BatchEmitOwnedPtrs(NumPlacementArgs + NumConstructorArgs, SubExprs);
@@ -1455,7 +1458,6 @@
S.EmitPtr(OperatorNew);
S.EmitPtr(OperatorDelete);
S.EmitPtr(Constructor);
- S.Emit(AllocType);
S.Emit(StartLoc);
S.Emit(EndLoc);
}
@@ -1466,19 +1468,19 @@
bool GlobalNew = D.ReadBool();
bool ParenTypeId = D.ReadBool();
bool Initializer = D.ReadBool();
+ bool Array = D.ReadBool();
unsigned NumPlacementArgs = D.ReadInt();
unsigned NumConstructorArgs = D.ReadInt();
- unsigned TotalExprs = NumPlacementArgs + NumConstructorArgs;
+ unsigned TotalExprs = Array + NumPlacementArgs + NumConstructorArgs;
Stmt** SubExprs = new Stmt*[TotalExprs];
D.BatchReadOwnedPtrs(TotalExprs, SubExprs, C);
FunctionDecl *OperatorNew = D.ReadPtr<FunctionDecl>();
FunctionDecl *OperatorDelete = D.ReadPtr<FunctionDecl>();
CXXConstructorDecl *Constructor = D.ReadPtr<CXXConstructorDecl>();
- QualType AllocType = QualType::ReadVal(D);
SourceLocation StartLoc = SourceLocation::ReadVal(D);
SourceLocation EndLoc = SourceLocation::ReadVal(D);
- return new CXXNewExpr(T, AllocType, GlobalNew, ParenTypeId, Initializer,
+ return new CXXNewExpr(T, GlobalNew, ParenTypeId, Initializer, Array,
NumPlacementArgs, NumConstructorArgs, SubExprs,
OperatorNew, OperatorDelete, Constructor, StartLoc,
EndLoc);
@@ -1486,8 +1488,8 @@
void CXXDeleteExpr::EmitImpl(Serializer& S) const {
S.Emit(getType());
- S.Emit(GlobalDelete);
- S.Emit(ArrayForm);
+ S.EmitBool(GlobalDelete);
+ S.EmitBool(ArrayForm);
S.EmitPtr(OperatorDelete);
S.EmitOwnedPtr(Argument);
S.Emit(Loc);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 192c70a..c3bbb52 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -28,9 +28,7 @@
/// specifier-qualifier-list abstract-declarator[opt]
///
/// Called type-id in C++.
-/// CXXNewMode is a special flag used by the parser of C++ new-expressions. It
-/// is simply passed on to ActOnTypeName.
-Parser::TypeTy *Parser::ParseTypeName(bool CXXNewMode) {
+Parser::TypeTy *Parser::ParseTypeName() {
// Parse the common declaration-specifiers piece.
DeclSpec DS;
ParseSpecifierQualifierList(DS);
@@ -39,7 +37,7 @@
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
ParseDeclarator(DeclaratorInfo);
- return Actions.ActOnTypeName(CurScope, DeclaratorInfo, CXXNewMode).Val;
+ return Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val;
}
/// ParseAttributes - Parse a non-empty attributes list.
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 09aea03..d995b88 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -645,6 +645,13 @@
/// new-placement:
/// '(' expression-list ')'
///
+/// new-type-id:
+/// type-specifier-seq new-declarator[opt]
+///
+/// new-declarator:
+/// ptr-operator new-declarator[opt]
+/// direct-new-declarator
+///
/// new-initializer:
/// '(' expression-list[opt] ')'
/// [C++0x] braced-init-list [TODO]
@@ -671,49 +678,58 @@
ExprVector PlacementArgs(Actions);
SourceLocation PlacementLParen, PlacementRParen;
- TypeTy *Ty = 0;
- SourceLocation TyStart, TyEnd;
bool ParenTypeId;
+ DeclSpec DS;
+ Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
if (Tok.is(tok::l_paren)) {
// If it turns out to be a placement, we change the type location.
PlacementLParen = ConsumeParen();
- TyStart = Tok.getLocation();
- if (ParseExpressionListOrTypeId(PlacementArgs, Ty))
+ if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
+ SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
return true;
- TyEnd = Tok.getLocation();
+ }
PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
- if (PlacementRParen.isInvalid())
+ if (PlacementRParen.isInvalid()) {
+ SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
return true;
+ }
- if (Ty) {
+ if (PlacementArgs.empty()) {
// Reset the placement locations. There was no placement.
PlacementLParen = PlacementRParen = SourceLocation();
ParenTypeId = true;
} else {
// We still need the type.
if (Tok.is(tok::l_paren)) {
- ConsumeParen();
- TyStart = Tok.getLocation();
- Ty = ParseTypeName(/*CXXNewMode=*/true);
+ SourceLocation LParen = ConsumeParen();
+ ParseSpecifierQualifierList(DS);
+ ParseDeclarator(DeclaratorInfo);
+ MatchRHSPunctuation(tok::r_paren, LParen);
ParenTypeId = true;
} else {
- TyStart = Tok.getLocation();
- Ty = ParseNewTypeId();
+ if (ParseCXXTypeSpecifierSeq(DS))
+ DeclaratorInfo.setInvalidType(true);
+ else
+ ParseDeclaratorInternal(DeclaratorInfo,
+ &Parser::ParseDirectNewDeclarator);
ParenTypeId = false;
}
- if (!Ty)
- return true;
- TyEnd = Tok.getLocation();
}
} else {
- TyStart = Tok.getLocation();
- Ty = ParseNewTypeId();
- if (!Ty)
- return true;
- TyEnd = Tok.getLocation();
+ // A new-type-id is a simplified type-id, where essentially the
+ // direct-declarator is replaced by a direct-new-declarator.
+ if (ParseCXXTypeSpecifierSeq(DS))
+ DeclaratorInfo.setInvalidType(true);
+ else
+ ParseDeclaratorInternal(DeclaratorInfo,
+ &Parser::ParseDirectNewDeclarator);
ParenTypeId = false;
}
+ if (DeclaratorInfo.getInvalidType()) {
+ SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
+ return true;
+ }
ExprVector ConstructorArgs(Actions);
SourceLocation ConstructorLParen, ConstructorRParen;
@@ -722,51 +738,25 @@
ConstructorLParen = ConsumeParen();
if (Tok.isNot(tok::r_paren)) {
CommaLocsTy CommaLocs;
- if (ParseExpressionList(ConstructorArgs, CommaLocs))
+ if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
+ SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
return true;
+ }
}
ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
- if (ConstructorRParen.isInvalid())
+ if (ConstructorRParen.isInvalid()) {
+ SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
return true;
+ }
}
return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
PlacementArgs.take(), PlacementArgs.size(),
- PlacementRParen, ParenTypeId, TyStart, Ty, TyEnd,
+ PlacementRParen, ParenTypeId, DeclaratorInfo,
ConstructorLParen, ConstructorArgs.take(),
ConstructorArgs.size(), ConstructorRParen);
}
-/// ParseNewTypeId - Parses a type ID as it appears in a new expression.
-/// The most interesting part of this is the new-declarator, which can be a
-/// multi-dimensional array, of which the first has a non-constant expression as
-/// the size, e.g.
-/// @code new int[runtimeSize()][2][2] @endcode
-///
-/// new-type-id:
-/// type-specifier-seq new-declarator[opt]
-///
-/// new-declarator:
-/// ptr-operator new-declarator[opt]
-/// direct-new-declarator
-///
-Parser::TypeTy * Parser::ParseNewTypeId()
-{
- DeclSpec DS;
- if (ParseCXXTypeSpecifierSeq(DS))
- return 0;
-
- // A new-declarator is a simplified version of a declarator. We use
- // ParseDeclaratorInternal, but pass our own direct declarator parser,
- // one that parses a direct-new-declarator.
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
- ParseDeclaratorInternal(DeclaratorInfo, &Parser::ParseDirectNewDeclarator);
-
- TypeTy *Ty = Actions.ActOnTypeName(CurScope, DeclaratorInfo,
- /*CXXNewMode=*/true).Val;
- return DeclaratorInfo.getInvalidType() ? 0 : Ty;
-}
-
/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
/// passed to ParseDeclaratorInternal.
///
@@ -806,12 +796,14 @@
/// new-placement:
/// '(' expression-list ')'
///
-bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs, TypeTy *&Ty)
+bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
+ Declarator &D)
{
// The '(' was already consumed.
if (isTypeIdInParens()) {
- Ty = ParseTypeName(/*CXXNewMode=*/true);
- return Ty == 0;
+ ParseSpecifierQualifierList(D.getMutableDeclSpec());
+ ParseDeclarator(D);
+ return D.getInvalidType();
}
// It's not a type, it has to be an expression list.
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 6f1cf88..7f3d0f4 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -245,16 +245,14 @@
//
QualType ConvertDeclSpecToType(const DeclSpec &DS);
void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
- QualType GetTypeForDeclarator(Declarator &D, Scope *S,
- bool CXXNewMode = false);
+ QualType GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip = 0);
DeclarationName GetNameForDeclarator(Declarator &D);
QualType ObjCGetTypeForMethodDefinition(DeclTy *D);
bool UnwrapSimilarPointerTypes(QualType& T1, QualType& T2);
- virtual TypeResult ActOnTypeName(Scope *S, Declarator &D,
- bool CXXNewMode = false);
+ virtual TypeResult ActOnTypeName(Scope *S, Declarator &D);
//===--------------------------------------------------------------------===//
// Symbol table / Decl tracking callbacks: SemaDecl.cpp.
@@ -828,13 +826,11 @@
SourceLocation PlacementLParen,
ExprTy **PlacementArgs, unsigned NumPlaceArgs,
SourceLocation PlacementRParen,
- bool ParenTypeId, SourceLocation TyStart,
- TypeTy *Ty, SourceLocation TyEnd,
+ bool ParenTypeId, Declarator &D,
SourceLocation ConstructorLParen,
ExprTy **ConstructorArgs, unsigned NumConsArgs,
SourceLocation ConstructorRParen);
- bool CheckAllocatedType(QualType AllocType, SourceLocation StartLoc,
- const SourceRange &TyR);
+ bool CheckAllocatedType(QualType AllocType, const Declarator &D);
/// ActOnCXXDelete - Parsed a C++ 'delete' expression
virtual ExprResult ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 3633da8..bfc367d 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -180,30 +180,60 @@
SourceLocation PlacementLParen,
ExprTy **PlacementArgs, unsigned NumPlaceArgs,
SourceLocation PlacementRParen, bool ParenTypeId,
- SourceLocation TyStart, TypeTy *Ty, SourceLocation TyEnd,
- SourceLocation ConstructorLParen,
+ Declarator &D, SourceLocation ConstructorLParen,
ExprTy **ConstructorArgs, unsigned NumConsArgs,
SourceLocation ConstructorRParen)
{
- QualType AllocType = QualType::getFromOpaquePtr(Ty);
- QualType CheckType = AllocType;
- // To leverage the existing parser as much as possible, array types are
- // parsed as VLAs. Unwrap for checking.
- if (const VariableArrayType *VLA = Context.getAsVariableArrayType(AllocType))
- CheckType = VLA->getElementType();
+ // FIXME: Throughout this function, we have rather bad location information.
+ // Implementing Declarator::getSourceRange() would go a long way toward
+ // fixing that.
- // Validate the type, and unwrap an array if any.
- if (CheckAllocatedType(CheckType, StartLoc, SourceRange(TyStart, TyEnd)))
+ Expr *ArraySize = 0;
+ unsigned Skip = 0;
+ // If the specified type is an array, unwrap it and save the expression.
+ if (D.getNumTypeObjects() > 0 &&
+ D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
+ DeclaratorChunk &Chunk = D.getTypeObject(0);
+ if (Chunk.Arr.hasStatic)
+ return Diag(Chunk.Loc, diag::err_static_illegal_in_new);
+ if (!Chunk.Arr.NumElts)
+ return Diag(Chunk.Loc, diag::err_array_new_needs_size);
+ ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts);
+ Skip = 1;
+ }
+
+ QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, Skip);
+ if (D.getInvalidType())
return true;
- QualType ResultType = Context.getPointerType(CheckType);
+ if (CheckAllocatedType(AllocType, D))
+ return true;
+
+ QualType ResultType = Context.getPointerType(AllocType);
// That every array dimension except the first is constant was already
// checked by the type check above.
+
// C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral
// or enumeration type with a non-negative value."
- // This was checked by ActOnTypeName, since C99 has the same restriction on
- // VLA expressions.
+ if (ArraySize) {
+ QualType SizeType = ArraySize->getType();
+ if (!SizeType->isIntegralType() && !SizeType->isEnumeralType())
+ return Diag(ArraySize->getSourceRange().getBegin(),
+ diag::err_array_size_not_integral)
+ << SizeType << ArraySize->getSourceRange();
+ // Let's see if this is a constant < 0. If so, we reject it out of hand.
+ // We don't care about special rules, so we tell the machinery it's not
+ // evaluated - it gives us a result in more cases.
+ llvm::APSInt Value;
+ if (ArraySize->isIntegerConstantExpr(Value, Context, 0, false)) {
+ if (Value < llvm::APSInt(
+ llvm::APInt::getNullValue(Value.getBitWidth()), false))
+ return Diag(ArraySize->getSourceRange().getBegin(),
+ diag::err_typecheck_negative_array_size)
+ << ArraySize->getSourceRange();
+ }
+ }
// --- Choosing an allocation function ---
// C++ 5.3.4p8 - 14 & 18
@@ -239,12 +269,14 @@
// 2) Otherwise, the object is direct-initialized.
CXXConstructorDecl *Constructor = 0;
Expr **ConsArgs = (Expr**)ConstructorArgs;
- if (const RecordType *RT = CheckType->getAsRecordType()) {
+ if (const RecordType *RT = AllocType->getAsRecordType()) {
// FIXME: This is incorrect for when there is an empty initializer and
// no user-defined constructor. Must zero-initialize, not default-construct.
Constructor = PerformInitializationByConstructor(
- CheckType, ConsArgs, NumConsArgs,
- TyStart, SourceRange(TyStart, ConstructorRParen),
+ AllocType, ConsArgs, NumConsArgs,
+ D.getDeclSpec().getSourceRange().getBegin(),
+ SourceRange(D.getDeclSpec().getSourceRange().getBegin(),
+ ConstructorRParen),
RT->getDecl()->getDeclName(),
NumConsArgs != 0 ? IK_Direct : IK_Default);
if (!Constructor)
@@ -252,9 +284,9 @@
} else {
if (!Init) {
// FIXME: Check that no subpart is const.
- if (CheckType.isConstQualified()) {
+ if (AllocType.isConstQualified()) {
Diag(StartLoc, diag::err_new_uninitialized_const)
- << SourceRange(StartLoc, TyEnd);
+ << D.getSourceRange();
return true;
}
} else if (NumConsArgs == 0) {
@@ -262,8 +294,8 @@
} else if (NumConsArgs == 1) {
// Object is direct-initialized.
// FIXME: WHAT DeclarationName do we pass in here?
- if (CheckInitializerTypes(ConsArgs[0], CheckType, StartLoc,
- DeclarationName() /*CheckType.getAsString()*/))
+ if (CheckInitializerTypes(ConsArgs[0], AllocType, StartLoc,
+ DeclarationName() /*AllocType.getAsString()*/))
return true;
} else {
Diag(StartLoc, diag::err_builtin_direct_init_more_than_one_arg)
@@ -274,16 +306,15 @@
// FIXME: Also check that the destructor is accessible. (C++ 5.3.4p16)
return new CXXNewExpr(UseGlobal, OperatorNew, PlaceArgs, NumPlaceArgs,
- ParenTypeId, AllocType, Constructor, Init,
+ ParenTypeId, ArraySize, Constructor, Init,
ConsArgs, NumConsArgs, OperatorDelete, ResultType,
- StartLoc, Init ? ConstructorRParen : TyEnd);
+ StartLoc, Init ? ConstructorRParen : SourceLocation());
}
/// CheckAllocatedType - Checks that a type is suitable as the allocated type
/// in a new-expression.
/// dimension off and stores the size expression in ArraySize.
-bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation StartLoc,
- const SourceRange &TyR)
+bool Sema::CheckAllocatedType(QualType AllocType, const Declarator &D)
{
// C++ 5.3.4p1: "[The] type shall be a complete object type, but not an
// abstract class type or array thereof.
@@ -291,29 +322,34 @@
// FIXME: Under C++ semantics, an incomplete object type is still an object
// type. This code assumes the C semantics, where it's not.
if (!AllocType->isObjectType()) {
- diag::kind msg;
+ unsigned type; // For the select in the message.
if (AllocType->isFunctionType()) {
- msg = diag::err_new_function;
+ type = 0;
} else if(AllocType->isIncompleteType()) {
- msg = diag::err_new_incomplete;
- } else if(AllocType->isReferenceType()) {
- msg = diag::err_new_reference;
+ type = 1;
} else {
- assert(false && "Unexpected type class");
- return true;
+ assert(AllocType->isReferenceType() && "What else could it be?");
+ type = 2;
}
- Diag(StartLoc, msg) << AllocType << TyR;
+ SourceRange TyR = D.getDeclSpec().getSourceRange();
+ // FIXME: This is very much a guess and won't work for, e.g., pointers.
+ if (D.getNumTypeObjects() > 0)
+ TyR.setEnd(D.getTypeObject(0).Loc);
+ Diag(TyR.getBegin(), diag::err_bad_new_type)
+ << AllocType.getAsString() << type << TyR;
return true;
}
- // Every dimension beyond the first shall be of constant size.
+ // Every dimension shall be of constant size.
+ unsigned i = 1;
while (const ArrayType *Array = Context.getAsArrayType(AllocType)) {
if (!Array->isConstantArrayType()) {
- // FIXME: Might be nice to get a better source range from somewhere.
- Diag(StartLoc, diag::err_new_array_nonconst) << TyR;
+ Diag(D.getTypeObject(i).Loc, diag::err_new_array_nonconst)
+ << static_cast<Expr*>(D.getTypeObject(i).Arr.NumElts)->getSourceRange();
return true;
}
AllocType = Array->getElementType();
+ ++i;
}
return false;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index d878e46..4487c1e 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -249,8 +249,8 @@
}
/// GetTypeForDeclarator - Convert the type for the specified declarator to Type
-/// instances.
-QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, bool CXXNewMode) {
+/// instances. Skip the outermost Skip type objects.
+QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
// long long is a C99 feature.
if (!getLangOptions().C99 && !getLangOptions().CPlusPlus0x &&
D.getDeclSpec().getTypeSpecWidth() == DeclSpec::TSW_longlong)
@@ -260,8 +260,8 @@
// Walk the DeclTypeInfo, building the recursive type as we go. DeclTypeInfos
// are ordered from the identifier out, which is opposite of what we want :).
- for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
- DeclaratorChunk &DeclType = D.getTypeObject(e-i-1);
+ for (unsigned i = Skip, e = D.getNumTypeObjects(); i != e; ++i) {
+ DeclaratorChunk &DeclType = D.getTypeObject(e-i-1+Skip);
switch (DeclType.Kind) {
default: assert(0 && "Unknown decltype!");
case DeclaratorChunk::BlockPointer:
@@ -340,8 +340,6 @@
break;
}
case DeclaratorChunk::Array: {
- // Only the outermost dimension gets special treatment.
- bool UseCXXNewMode = CXXNewMode && i == e-1;
DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
Expr *ArraySize = static_cast<Expr*>(ATI.NumElts);
ArrayType::ArraySizeModifier ASM;
@@ -394,11 +392,9 @@
if (!ArraySize) {
T = Context.getIncompleteArrayType(T, ASM, ATI.TypeQuals);
} else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
- !T->isConstantSizeType() || UseCXXNewMode) {
+ !T->isConstantSizeType()) {
// Per C99, a variable array is an array with either a non-constant
// size or an element type that has a non-constant-size
- // We also force this for parsing C++ new-expressions, since the
- // outermost dimension is always treated as variable.
T = Context.getVariableArrayType(T, ArraySize, ASM, ATI.TypeQuals);
} else {
// C99 6.7.5.2p1: If the expression is a constant expression, it shall
@@ -418,9 +414,7 @@
T = Context.getConstantArrayType(T, ConstVal, ASM, ATI.TypeQuals);
}
// If this is not C99, extwarn about VLA's and C99 array size modifiers.
- // Unless we're in C++ new mode. ActOnCXXNew will complain about them
- // there, and they're hard errors.
- if (!getLangOptions().C99 && !CXXNewMode &&
+ if (!getLangOptions().C99 &&
(ASM != ArrayType::Normal ||
(ArraySize && !ArraySize->isIntegerConstantExpr(Context))))
Diag(D.getIdentifierLoc(), diag::ext_vla);
@@ -617,12 +611,12 @@
return false;
}
-Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D, bool CXXNewMode) {
+Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
// C99 6.7.6: Type names have no identifier. This is already validated by
// the parser.
assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
- QualType T = GetTypeForDeclarator(D, S, CXXNewMode);
+ QualType T = GetTypeForDeclarator(D, S);
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");