diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 78 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 30 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 5 |
6 files changed, 98 insertions, 25 deletions
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; } |