diff options
author | Chris Lattner <sabre@nondot.org> | 2008-04-10 02:22:51 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-04-10 02:22:51 +0000 |
commit | 8123a95c33b792d35c2e4992ba6e27882748fb0d (patch) | |
tree | 33cd02a28ced427832214e01d1cfdca997f262b3 /lib/Sema/SemaDeclCXX.cpp | |
parent | 05cbe1a44e6143d44aac0e769ba120e8c45f34ce (diff) |
Several improvements from Doug Gregor related to default
argument handling. I'll fix up the c89 (void) thing next.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49459 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index e7bf7bff4b..3211e22890 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -14,11 +14,79 @@ #include "Sema.h" #include "clang/Basic/LangOptions.h" #include "clang/AST/Expr.h" +#include "clang/AST/StmtVisitor.h" #include "clang/AST/Type.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/Compiler.h" using namespace clang; +//===----------------------------------------------------------------------===// +// CheckDefaultArgumentVisitor +//===----------------------------------------------------------------------===// + +/// CheckDefaultArgumentVisitor - Traverses the default argument of a +/// parameter to determine whether it contains any ill-formed +/// subexpressions. For example, this will diagnose the use of local +/// variables or parameters within the default argument expression. +class VISIBILITY_HIDDEN CheckDefaultArgumentVisitor + : public StmtVisitor<CheckDefaultArgumentVisitor, bool> +{ + Sema *S; + +public: + explicit CheckDefaultArgumentVisitor(Sema *s) : S(s) {} + + bool VisitExpr(Expr *Node); + bool VisitDeclRefExpr(DeclRefExpr *DRE); +}; + +/// VisitExpr - Visit all of the children of this expression. +bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) { + bool IsInvalid = false; + for (Stmt::child_iterator first = Node->child_begin(), + last = Node->child_end(); + first != last; ++first) + IsInvalid |= Visit(*first); + + return IsInvalid; +} + +/// VisitDeclRefExpr - Visit a reference to a declaration, to +/// determine whether this declaration can be used in the default +/// argument expression. +bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) { + ValueDecl *Decl = DRE->getDecl(); + if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(Decl)) { + // C++ [dcl.fct.default]p9 + // Default arguments are evaluated each time the function is + // called. The order of evaluation of function arguments is + // unspecified. Consequently, parameters of a function shall not + // be used in default argument expressions, even if they are not + // evaluated. Parameters of a function declared before a default + // argument expression are in scope and can hide namespace and + // class member names. + return S->Diag(DRE->getSourceRange().getBegin(), + diag::err_param_default_argument_references_param, + Param->getName()); + } else if (BlockVarDecl *BlockVar = dyn_cast<BlockVarDecl>(Decl)) { + // C++ [dcl.fct.default]p7 + // Local variables shall not be used in default argument + // expressions. + return S->Diag(DRE->getSourceRange().getBegin(), + diag::err_param_default_argument_references_local, + BlockVar->getName()); + } + + // FIXME: when Clang has support for member functions, "this" + // will also need to be diagnosted. + + return false; +} + +/// ActOnParamDefaultArgument - Check whether the default argument +/// provided for a function parameter is well-formed. If so, attach it +/// to the parameter declaration. void Sema::ActOnParamDefaultArgument(DeclTy *param, SourceLocation EqualLoc, ExprTy *defarg) { @@ -66,6 +134,11 @@ Sema::ActOnParamDefaultArgument(DeclTy *param, SourceLocation EqualLoc, // parameter-declaration-clause, it shall not occur within a // declarator or abstract-declarator of a parameter-declaration. + // Check that the default argument is well-formed + CheckDefaultArgumentVisitor DefaultArgChecker(this); + if (DefaultArgChecker.Visit(DefaultArg.get())) + return; + // Okay: add the default argument to the parameter Param->setDefaultArg(DefaultArg.take()); } |