summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2008-12-05 23:32:09 +0000
committerDouglas Gregor <dgregor@apple.com>2008-12-05 23:32:09 +0000
commit4619e439b64a251fe35f7a5821aa90d78b879fa9 (patch)
treed67783abf73134f163d2d6151c65b7bcb5cbc4ac /clang/lib
parent0733759b5aaabd81eb2348651fb726c075c08e0c (diff)
downloadbcm5719-llvm-4619e439b64a251fe35f7a5821aa90d78b879fa9.tar.gz
bcm5719-llvm-4619e439b64a251fe35f7a5821aa90d78b879fa9.zip
Introduce basic support for dependent types, type-dependent
expressions, and value-dependent expressions. This permits us to parse some template definitions. This is not a complete solution; we're missing type- and value-dependent computations for most of the expression types, and we're missing checks for dependent types and type-dependent expressions throughout Sema. llvm-svn: 60615
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp48
-rw-r--r--clang/lib/AST/CFG.cpp2
-rw-r--r--clang/lib/AST/Expr.cpp30
-rw-r--r--clang/lib/AST/StmtIterator.cpp2
-rw-r--r--clang/lib/AST/Type.cpp37
-rw-r--r--clang/lib/AST/TypeSerialization.cpp20
-rw-r--r--clang/lib/CodeGen/CodeGenTypes.cpp1
-rw-r--r--clang/lib/Sema/SemaDecl.cpp5
-rw-r--r--clang/lib/Sema/SemaExpr.cpp78
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp4
-rw-r--r--clang/lib/Sema/SemaStmt.cpp30
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp1
-rw-r--r--clang/lib/Sema/SemaType.cpp5
13 files changed, 234 insertions, 29 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 7c8b4b1b413..35647cf02aa 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -183,7 +183,14 @@ void ASTContext::InitBuiltinTypes() {
InitBuiltinType(WCharTy, BuiltinType::WChar);
// Placeholder type for functions.
- InitBuiltinType(OverloadTy, BuiltinType::Overload);
+ InitBuiltinType(OverloadTy, BuiltinType::Overload);
+
+ // Placeholder type for type-dependent expressions whose type is
+ // completely unknown. No code should ever check a type against
+ // DependentTy and users should never see it; however, it is here to
+ // help diagnose failures to properly check for type-dependent
+ // expressions.
+ InitBuiltinType(DependentTy, BuiltinType::Dependent);
// C99 6.2.5p11.
FloatComplexTy = getComplexType(FloatTy);
@@ -235,6 +242,8 @@ ASTContext::getTypeInfo(const Type *T) {
assert(0 && "Incomplete types have no size!");
case Type::VariableArray:
assert(0 && "VLAs not implemented yet!");
+ case Type::DependentSizedArray:
+ assert(0 && "Dependently-sized arrays don't have a known size");
case Type::ConstantArray: {
const ConstantArrayType *CAT = cast<ConstantArrayType>(T);
@@ -759,6 +768,28 @@ QualType ASTContext::getVariableArrayType(QualType EltTy, Expr *NumElts,
return QualType(New, 0);
}
+/// getDependentSizedArrayType - Returns a non-unique reference to
+/// the type for a dependently-sized array of the specified element
+/// type. FIXME: We will need these to be uniqued, or at least
+/// comparable, at some point.
+QualType ASTContext::getDependentSizedArrayType(QualType EltTy, Expr *NumElts,
+ ArrayType::ArraySizeModifier ASM,
+ unsigned EltTypeQuals) {
+ assert((NumElts->isTypeDependent() || NumElts->isValueDependent()) &&
+ "Size must be type- or value-dependent!");
+
+ // Since we don't unique expressions, it isn't possible to unique
+ // dependently-sized array types.
+
+ DependentSizedArrayType *New
+ = new DependentSizedArrayType(EltTy, QualType(), NumElts,
+ ASM, EltTypeQuals);
+
+ DependentSizedArrayTypes.push_back(New);
+ Types.push_back(New);
+ return QualType(New, 0);
+}
+
QualType ASTContext::getIncompleteArrayType(QualType EltTy,
ArrayType::ArraySizeModifier ASM,
unsigned EltTypeQuals) {
@@ -1174,6 +1205,11 @@ QualType ASTContext::getCanonicalType(QualType T) {
return getIncompleteArrayType(NewEltTy, IAT->getSizeModifier(),
IAT->getIndexTypeQualifier());
+ if (DependentSizedArrayType *DSAT = dyn_cast<DependentSizedArrayType>(AT))
+ return getDependentSizedArrayType(NewEltTy, DSAT->getSizeExpr(),
+ DSAT->getSizeModifier(),
+ DSAT->getIndexTypeQualifier());
+
// FIXME: What is the ownership of size expressions in VLAs?
VariableArrayType *VAT = cast<VariableArrayType>(AT);
return getVariableArrayType(NewEltTy, VAT->getSizeExpr(),
@@ -1246,6 +1282,16 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) {
return cast<ArrayType>(getIncompleteArrayType(NewEltTy,
IAT->getSizeModifier(),
IAT->getIndexTypeQualifier()));
+
+ // FIXME: What is the ownership of size expressions in
+ // dependent-sized array types?
+ if (const DependentSizedArrayType *DSAT
+ = dyn_cast<DependentSizedArrayType>(ATy))
+ return cast<ArrayType>(
+ getDependentSizedArrayType(NewEltTy,
+ DSAT->getSizeExpr(),
+ DSAT->getSizeModifier(),
+ DSAT->getIndexTypeQualifier()));
// FIXME: What is the ownership of size expressions in VLAs?
const VariableArrayType *VAT = cast<VariableArrayType>(ATy);
diff --git a/clang/lib/AST/CFG.cpp b/clang/lib/AST/CFG.cpp
index 82336a44e08..69e82f2b832 100644
--- a/clang/lib/AST/CFG.cpp
+++ b/clang/lib/AST/CFG.cpp
@@ -154,6 +154,8 @@ private:
bool badCFG;
};
+// FIXME: Add support for dependent-sized array types in C++?
+// Does it even make sense to build a CFG for an uninstantiated template?
static VariableArrayType* FindVA(Type* t) {
while (ArrayType* vt = dyn_cast<ArrayType>(t)) {
if (VariableArrayType* vat = dyn_cast<VariableArrayType>(vt))
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index a3264b010b7..14db18c1345 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -103,7 +103,10 @@ const char *UnaryOperator::getOpcodeStr(Opcode Op) {
CallExpr::CallExpr(StmtClass SC, Expr *fn, Expr **args, unsigned numargs,
QualType t, SourceLocation rparenloc)
- : Expr(SC, t), NumArgs(numargs) {
+ : Expr(SC, t,
+ fn->isTypeDependent() || hasAnyTypeDependentArguments(args, numargs),
+ fn->isValueDependent() || hasAnyValueDependentArguments(args, numargs)),
+ NumArgs(numargs) {
SubExprs = new Stmt*[numargs+1];
SubExprs[FN] = fn;
for (unsigned i = 0; i != numargs; ++i)
@@ -113,7 +116,10 @@ CallExpr::CallExpr(StmtClass SC, Expr *fn, Expr **args, unsigned numargs,
CallExpr::CallExpr(Expr *fn, Expr **args, unsigned numargs, QualType t,
SourceLocation rparenloc)
- : Expr(CallExprClass, t), NumArgs(numargs) {
+ : Expr(CallExprClass, t,
+ fn->isTypeDependent() || hasAnyTypeDependentArguments(args, numargs),
+ fn->isValueDependent() || hasAnyValueDependentArguments(args, numargs)),
+ NumArgs(numargs) {
SubExprs = new Stmt*[numargs+1];
SubExprs[FN] = fn;
for (unsigned i = 0; i != numargs; ++i)
@@ -631,6 +637,26 @@ Expr *Expr::IgnoreParenCasts() {
}
}
+/// hasAnyTypeDependentArguments - Determines if any of the expressions
+/// in Exprs is type-dependent.
+bool Expr::hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs) {
+ for (unsigned I = 0; I < NumExprs; ++I)
+ if (Exprs[I]->isTypeDependent())
+ return true;
+
+ return false;
+}
+
+/// hasAnyValueDependentArguments - Determines if any of the expressions
+/// in Exprs is value-dependent.
+bool Expr::hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs) {
+ for (unsigned I = 0; I < NumExprs; ++I)
+ if (Exprs[I]->isValueDependent())
+ return true;
+
+ return false;
+}
+
bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
switch (getStmtClass()) {
default:
diff --git a/clang/lib/AST/StmtIterator.cpp b/clang/lib/AST/StmtIterator.cpp
index 46882422e1c..48003450191 100644
--- a/clang/lib/AST/StmtIterator.cpp
+++ b/clang/lib/AST/StmtIterator.cpp
@@ -16,6 +16,8 @@
using namespace clang;
+// FIXME: Add support for dependent-sized array types in C++?
+// Does it even make sense to build a CFG for an uninstantiated template?
static inline VariableArrayType* FindVA(Type* t) {
while (ArrayType* vt = dyn_cast<ArrayType>(t)) {
if (VariableArrayType* vat = dyn_cast<VariableArrayType>(vt))
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 303fc7e7ca5..5909c976aa6 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -43,6 +43,10 @@ void VariableArrayType::Destroy(ASTContext& C) {
delete this;
}
+void DependentSizedArrayType::Destroy(ASTContext& C) {
+ SizeExpr->Destroy(C);
+ delete this;
+}
/// getArrayElementTypeNoTypeQual - If this is an array type, return the
/// element type of the array, potentially with type qualifiers missing.
@@ -634,11 +638,12 @@ bool Type::isAggregateType() const {
/// isConstantSizeType - Return true if this is not a variable sized type,
/// according to the rules of C99 6.7.5p3. It is not legal to call this on
-/// incomplete types.
+/// incomplete types or dependent types.
bool Type::isConstantSizeType() const {
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
return ASQT->getBaseType()->isConstantSizeType();
assert(!isIncompleteType() && "This doesn't make sense for incomplete types");
+ assert(!isDependentType() && "This doesn't make sense for dependent types");
// The VAT must have a size, as it is known to be complete.
return !isa<VariableArrayType>(CanonicalType);
}
@@ -706,6 +711,7 @@ const char *BuiltinType::getName() const {
case LongDouble: return "long double";
case WChar: return "wchar_t";
case Overload: return "<overloaded function type>";
+ case Dependent: return "<dependent type>";
}
}
@@ -780,6 +786,11 @@ QualType TypedefType::LookThroughTypedefs() const {
}
}
+TypeOfExpr::TypeOfExpr(Expr *E, QualType can)
+ : Type(TypeOfExp, can, E->isTypeDependent()), TOExpr(E) {
+ assert(!isa<TypedefType>(can) && "Invalid canonical type");
+}
+
bool RecordType::classof(const TagType *TT) {
return isa<RecordDecl>(TT->getDecl());
}
@@ -932,6 +943,30 @@ void VariableArrayType::getAsStringInternal(std::string &S) const {
getElementType().getAsStringInternal(S);
}
+void DependentSizedArrayType::getAsStringInternal(std::string &S) const {
+ S += '[';
+
+ if (getIndexTypeQualifier()) {
+ AppendTypeQualList(S, getIndexTypeQualifier());
+ S += ' ';
+ }
+
+ if (getSizeModifier() == Static)
+ S += "static";
+ else if (getSizeModifier() == Star)
+ S += '*';
+
+ if (getSizeExpr()) {
+ std::string SStr;
+ llvm::raw_string_ostream s(SStr);
+ getSizeExpr()->printPretty(s);
+ S += s.str();
+ }
+ S += ']';
+
+ getElementType().getAsStringInternal(S);
+}
+
void VectorType::getAsStringInternal(std::string &S) const {
// FIXME: We prefer to print the size directly here, but have no way
// to get the size of the type.
diff --git a/clang/lib/AST/TypeSerialization.cpp b/clang/lib/AST/TypeSerialization.cpp
index 3bdc946de7e..8e35f187a3e 100644
--- a/clang/lib/AST/TypeSerialization.cpp
+++ b/clang/lib/AST/TypeSerialization.cpp
@@ -315,6 +315,26 @@ Type* VariableArrayType::CreateImpl(ASTContext& Context, Deserializer& D) {
}
//===----------------------------------------------------------------------===//
+// DependentSizedArrayType
+//===----------------------------------------------------------------------===//
+
+void DependentSizedArrayType::EmitImpl(Serializer& S) const {
+ S.Emit(getElementType());
+ S.EmitInt(getSizeModifier());
+ S.EmitInt(getIndexTypeQualifier());
+ S.EmitOwnedPtr(SizeExpr);
+}
+
+Type* DependentSizedArrayType::CreateImpl(ASTContext& Context, Deserializer& D) {
+ QualType ElTy = QualType::ReadVal(D);
+ ArraySizeModifier am = static_cast<ArraySizeModifier>(D.ReadInt());
+ unsigned ITQ = D.ReadInt();
+ Expr* SizeExpr = D.ReadOwnedPtr<Expr>(Context);
+
+ return Context.getDependentSizedArrayType(ElTy,SizeExpr,am,ITQ).getTypePtr();
+}
+
+//===----------------------------------------------------------------------===//
// IncompleteArrayType
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index fbf11204070..85b10399a41 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -191,6 +191,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
switch (Ty.getTypeClass()) {
case Type::TypeName: // typedef isn't canonical.
case Type::TemplateTypeParm:// template type parameters never generated
+ case Type::DependentSizedArray: // dependent types are never generated
case Type::TypeOfExp: // typeof isn't canonical.
case Type::TypeOfTyp: // typeof isn't canonical.
assert(0 && "Non-canonical type, shouldn't happen");
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index c893d275978..e581b100dcc 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -870,9 +870,8 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
if (PrevDecl && isTemplateParameterDecl(PrevDecl)) {
// Maybe we will complain about the shadowed template parameter.
- InvalidDecl
- = InvalidDecl || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
- PrevDecl);
+ InvalidDecl = InvalidDecl
+ || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
// Just pretend that we didn't see the previous declaration.
PrevDecl = 0;
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index ec86b9f2a6b..e4beb74fc5d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -490,7 +490,52 @@ Sema::ExprResult Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
}
// If this reference is not in a block or if the referenced variable is
// within the block, create a normal DeclRefExpr.
- return new DeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc);
+
+ // C++ [temp.dep.expr]p3:
+ // An id-expression is type-dependent if it contains:
+ bool TypeDependent = false;
+
+ // - an identifier that was declared with a dependent type,
+ if (VD->getType()->isDependentType())
+ TypeDependent = true;
+ // - FIXME: a template-id that is dependent,
+ // - a conversion-function-id that specifies a dependent type,
+ else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
+ Name.getCXXNameType()->isDependentType())
+ TypeDependent = true;
+ // - a nested-name-specifier that contains a class-name that
+ // names a dependent type.
+ else if (SS && !SS->isEmpty()) {
+ for (DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep());
+ DC; DC = DC->getParent()) {
+ // FIXME: could stop early at namespace scope.
+ if (DC->isCXXRecord()) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
+ if (Context.getTypeDeclType(Record)->isDependentType()) {
+ TypeDependent = true;
+ break;
+ }
+ }
+ }
+ }
+
+ // C++ [temp.dep.constexpr]p2:
+ //
+ // An identifier is value-dependent if it is:
+ bool ValueDependent = false;
+
+ // - a name declared with a dependent type,
+ if (TypeDependent)
+ ValueDependent = true;
+ // - the name of a non-type template parameter,
+ else if (isa<NonTypeTemplateParmDecl>(VD))
+ ValueDependent = true;
+ // - a constant with integral or enumeration type and is
+ // initialized with an expression that is value-dependent
+ // (FIXME!).
+
+ return new DeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc,
+ TypeDependent, ValueDependent);
}
Sema::ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
@@ -1279,6 +1324,11 @@ ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc,
FunctionDecl *FDecl = NULL;
OverloadedFunctionDecl *Ovl = NULL;
+ // FIXME: Will need to cache the results of name lookup (including
+ // ADL) in Fn.
+ if (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(Args, NumArgs))
+ return new CallExpr(Fn, Args, NumArgs, Context.DependentTy, RParenLoc);
+
// If we're directly calling a function or a set of overloaded
// functions, get the appropriate declaration.
{
@@ -1318,6 +1368,7 @@ ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc,
// of arguments and function on error.
llvm::OwningPtr<CallExpr> TheCall(new CallExpr(Fn, Args, NumArgs,
Context.BoolTy, RParenLoc));
+
const FunctionType *FuncT;
if (!Fn->getType()->isBlockPointerType()) {
// C99 6.5.2.2p1 - "The expression that denotes the called function shall
@@ -1470,6 +1521,8 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr) {
// type needs to be scalar.
if (castType->isVoidType()) {
// Cast to void allows any expr type.
+ } else if (castType->isDependentType() || castExpr->isTypeDependent()) {
+ // We can't check any more until template instantiation time.
} else if (!castType->isScalarType() && !castType->isVectorType()) {
// GCC struct/union extension: allow cast to self.
if (Context.getCanonicalType(castType) !=
@@ -1541,13 +1594,17 @@ inline QualType Sema::CheckConditionalOperands( // C99 6.5.15
QualType rexT = rex->getType();
// first, check the condition.
- if (!condT->isScalarType()) { // C99 6.5.15p2
- Diag(cond->getLocStart(), diag::err_typecheck_cond_expect_scalar) << condT;
- return QualType();
+ if (!cond->isTypeDependent()) {
+ if (!condT->isScalarType()) { // C99 6.5.15p2
+ Diag(cond->getLocStart(), diag::err_typecheck_cond_expect_scalar) << condT;
+ return QualType();
+ }
}
// Now check the two expressions.
-
+ if ((lex && lex->isTypeDependent()) || (rex && rex->isTypeDependent()))
+ return Context.DependentTy;
+
// If both operands have arithmetic type, do the usual arithmetic conversions
// to find a common type: C99 6.5.15p3,5.
if (lexT->isArithmeticType() && rexT->isArithmeticType()) {
@@ -2959,6 +3016,17 @@ Action::ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
assert((lhs != 0) && "ActOnBinOp(): missing left expression");
assert((rhs != 0) && "ActOnBinOp(): missing right expression");
+ // If either expression is type-dependent, just build the AST.
+ // FIXME: We'll need to perform some caching of the result of name
+ // lookup for operator+.
+ if (lhs->isTypeDependent() || rhs->isTypeDependent()) {
+ if (Opc > BinaryOperator::Assign && Opc <= BinaryOperator::OrAssign)
+ return new CompoundAssignOperator(lhs, rhs, Opc, Context.DependentTy,
+ Context.DependentTy, TokLoc);
+ else
+ return new BinaryOperator(lhs, rhs, Opc, Context.DependentTy, TokLoc);
+ }
+
if (getLangOptions().CPlusPlus &&
(lhs->getType()->isRecordType() || lhs->getType()->isEnumeralType() ||
rhs->getType()->isRecordType() || rhs->getType()->isEnumeralType())) {
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 1e9b945a181..c4cab3316ba 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -163,9 +163,9 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
//
if (Ty->isArrayType())
return Diag(TyBeginLoc, diag::err_value_init_for_array_type) << FullRange;
- if (Ty->isIncompleteType() && !Ty->isVoidType())
+ if (!Ty->isDependentType() && Ty->isIncompleteType() && !Ty->isVoidType())
return Diag(TyBeginLoc, diag::err_invalid_incomplete_type_use)
- << Ty << FullRange;
+ << Ty << FullRange;
return new CXXZeroInitValueExpr(Ty, TyBeginLoc, RParenLoc);
}
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 0159f5f0a53..21f897f639b 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -782,21 +782,23 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprTy *rex) {
return new ReturnStmt(ReturnLoc, (Expr*)0);
}
- // we have a non-void function with an expression, continue checking
- QualType RetValType = RetValExp->getType();
-
- // C99 6.8.6.4p3(136): The return statement is not an assignment. The
- // overlap restriction of subclause 6.5.16.1 does not apply to the case of
- // function return.
-
- // In C++ the return statement is handled via a copy initialization.
- // the C version of which boils down to
- // CheckSingleAssignmentConstraints.
- if (PerformCopyInitialization(RetValExp, FnRetType, "returning"))
- return true;
-
- if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+ if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) {
+ // we have a non-void function with an expression, continue checking
+ QualType RetValType = RetValExp->getType();
+
+ // C99 6.8.6.4p3(136): The return statement is not an assignment. The
+ // overlap restriction of subclause 6.5.16.1 does not apply to the case of
+ // function return.
+
+ // In C++ the return statement is handled via a copy initialization.
+ // the C version of which boils down to
+ // CheckSingleAssignmentConstraints.
+ if (PerformCopyInitialization(RetValExp, FnRetType, "returning"))
+ return true;
+ if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+ }
+
return new ReturnStmt(ReturnLoc, (Expr*)RetValExp);
}
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 749d181baf0..092c9d2236a 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -12,6 +12,7 @@
//+//===----------------------------------------------------------------------===/
#include "Sema.h"
+#include "clang/AST/Expr.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Basic/LangOptions.h"
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 4487c1e4160..2423e1271b8 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -391,6 +391,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
llvm::APSInt ConstVal(32);
if (!ArraySize) {
T = Context.getIncompleteArrayType(T, ASM, ATI.TypeQuals);
+ } else if (ArraySize->isValueDependent()) {
+ T = Context.getDependentSizedArrayType(T, ArraySize, ASM, ATI.TypeQuals);
} else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
!T->isConstantSizeType()) {
// Per C99, a variable array is an array with either a non-constant
@@ -416,7 +418,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
// If this is not C99, extwarn about VLA's and C99 array size modifiers.
if (!getLangOptions().C99 &&
(ASM != ArrayType::Normal ||
- (ArraySize && !ArraySize->isIntegerConstantExpr(Context))))
+ (ArraySize && !ArraySize->isValueDependent() &&
+ !ArraySize->isIntegerConstantExpr(Context))))
Diag(D.getIdentifierLoc(), diag::ext_vla);
break;
}
OpenPOWER on IntegriCloud