diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 57c9763f7d2b..d3bf1b96d641 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -555,7 +555,10 @@ private: public: UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l) - : Expr(UnaryOperatorClass, type), Val(input), Opc(opc), Loc(l) {} + : Expr(UnaryOperatorClass, type, + input->isTypeDependent() && opc != OffsetOf, + input->isValueDependent()), + Val(input), Opc(opc), Loc(l) {} Opcode getOpcode() const { return Opc; } Expr *getSubExpr() const { return cast(Val); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 515169c557e4..096bcbe37b09 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2876,6 +2876,9 @@ static NamedDecl *getPrimaryDecl(Expr *E) { /// In C++, the operand might be an overloaded function name, in which case /// we allow the '&' but retain the overloaded-function type. QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { + if (op->isTypeDependent()) + return Context.DependentTy; + if (getLangOptions().C99) { // Implement C99-only parts of addressof rules. if (UnaryOperator* uOp = dyn_cast(op)) { diff --git a/clang/lib/Sema/SemaNamedCast.cpp b/clang/lib/Sema/SemaNamedCast.cpp index af1e2e000881..3d3572d00ce4 100644 --- a/clang/lib/Sema/SemaNamedCast.cpp +++ b/clang/lib/Sema/SemaNamedCast.cpp @@ -65,26 +65,34 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, SourceRange OpRange(OpLoc, RParenLoc); SourceRange DestRange(LAngleBracketLoc, RAngleBracketLoc); + // If the type is dependent, we won't do the semantic analysis now. + // FIXME: should we check this in a more fine-grained manner? + bool TypeDependent = DestType->isDependentType() || Ex->isTypeDependent(); + switch (Kind) { default: assert(0 && "Unknown C++ cast!"); case tok::kw_const_cast: - CheckConstCast(*this, Ex, DestType, OpRange, DestRange); + if (!TypeDependent) + CheckConstCast(*this, Ex, DestType, OpRange, DestRange); return new CXXConstCastExpr(DestType.getNonReferenceType(), Ex, DestType, OpLoc); case tok::kw_dynamic_cast: - CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange); + if (!TypeDependent) + CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange); return new CXXDynamicCastExpr(DestType.getNonReferenceType(), Ex, DestType, OpLoc); case tok::kw_reinterpret_cast: - CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange); + if (!TypeDependent) + CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange); return new CXXReinterpretCastExpr(DestType.getNonReferenceType(), Ex, DestType, OpLoc); case tok::kw_static_cast: - CheckStaticCast(*this, Ex, DestType, OpRange); + if (!TypeDependent) + CheckStaticCast(*this, Ex, DestType, OpRange); return new CXXStaticCastExpr(DestType.getNonReferenceType(), Ex, DestType, OpLoc); } diff --git a/clang/test/SemaCXX/type-dependent-exprs.cpp b/clang/test/SemaCXX/type-dependent-exprs.cpp index 8d71073a0c22..15808c676964 100644 --- a/clang/test/SemaCXX/type-dependent-exprs.cpp +++ b/clang/test/SemaCXX/type-dependent-exprs.cpp @@ -1,4 +1,8 @@ // RUN: clang -fsyntax-only -verify %s +class X { +public: + virtual int f(); +}; void g(int); @@ -8,6 +12,10 @@ T f(T x) { (void)T(0); (void)(x += 0); (void)(x? x : x); + (void)static_cast(x); + (void)reinterpret_cast(x); + (void)dynamic_cast(&x); + (void)const_cast(x); return g(x); h(x); // h is a dependent name g(1, 1); // expected-error{{too many arguments to function call}}