From: Chris Lattner Date: Sat, 12 Apr 2008 23:52:44 +0000 (+0000) Subject: Default argument cleanups and minor improvements, patch by X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9e979557eea3875c9e3d100c68188233dd7f46c0;p=clang Default argument cleanups and minor improvements, patch by Doug Gregor! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49598 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index ac08f96508..8ce0be561f 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -352,6 +352,11 @@ public: return ParamInfo[i]; } void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams); + + /// getMinRequiredArguments - Returns the minimum number of arguments + /// needed to call this function. This may be fewer than the number of + /// function parameters, if some of the parameters have default + /// arguments (in C++). unsigned getMinRequiredArguments() const; QualType getResultType() const { diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 039b16f846..98bfbe945b 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -149,7 +149,7 @@ namespace clang { Expr *getExpr() { return Param->getDefaultArg(); } virtual SourceRange getSourceRange() const { - // Default argument expressions have no represntation in the + // Default argument expressions have no representation in the // source, so they have an empty source range. return SourceRange(); } diff --git a/include/clang/Rewrite/RewriteRope.h b/include/clang/Rewrite/RewriteRope.h index 8d2fbe3857..c10b13242c 100644 --- a/include/clang/Rewrite/RewriteRope.h +++ b/include/clang/Rewrite/RewriteRope.h @@ -120,6 +120,7 @@ class RewriteRope { RopeRefCountString *AllocBuffer; unsigned AllocOffs; enum { AllocChunkSize = 4080 }; + public: RewriteRope() : CurSize(0), AllocBuffer(0), AllocOffs(AllocChunkSize) {} ~RewriteRope() { clear(); } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index c0ec3085e5..bcb117dbc6 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -425,7 +425,7 @@ void FunctionDecl::setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) { /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of /// function parameters, if some of the parameters have default -/// arguments. +/// arguments (in C++). unsigned FunctionDecl::getMinRequiredArguments() const { unsigned NumRequiredArgs = getNumParams(); while (NumRequiredArgs > 0 diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index e3d6b4f788..7eeb64d578 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1343,13 +1343,6 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D) { ConsumeToken(); // Parse the default argument - // FIXME: For C++, name lookup from within the default argument - // should be able to find parameter names, but we haven't put them - // in the scope. This means that we will accept ill-formed code - // such as: - // - // int x; - // void f(int x = x) { } ExprResult DefArgResult = ParseAssignmentExpression(); if (DefArgResult.isInvalid) { SkipUntil(tok::comma, tok::r_paren, true, true); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 3211e22890..89440c0cf4 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -25,63 +25,68 @@ 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 -{ - 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(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(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()); +namespace { + /// CheckDefaultArgumentVisitor - C++ [dcl.fct.default] 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 + { + Expr *DefaultArg; + Sema *S; + + public: + CheckDefaultArgumentVisitor(Expr *defarg, Sema *s) + : DefaultArg(defarg), 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; } - // FIXME: when Clang has support for member functions, "this" - // will also need to be diagnosted. + /// 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(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(), DefaultArg->getSourceRange()); + } else if (BlockVarDecl *BlockVar = dyn_cast(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(), DefaultArg->getSourceRange()); + } - return false; + // FIXME: when Clang has support for member functions, "this" + // will also need to be diagnosed. + + return false; + } } /// ActOnParamDefaultArgument - Check whether the default argument @@ -135,7 +140,7 @@ Sema::ActOnParamDefaultArgument(DeclTy *param, SourceLocation EqualLoc, // declarator or abstract-declarator of a parameter-declaration. // Check that the default argument is well-formed - CheckDefaultArgumentVisitor DefaultArgChecker(this); + CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg.get(), this); if (DefaultArgChecker.Visit(DefaultArg.get())) return; diff --git a/test/Sema/default2.cpp b/test/Sema/default2.cpp index d72f5506bc..59489daf7b 100644 --- a/test/Sema/default2.cpp +++ b/test/Sema/default2.cpp @@ -25,3 +25,5 @@ void h() int i; extern void h2(int x = sizeof(i)); // expected-error {{default argument references local variable 'i' of enclosing function}} } + +void g2(int x, int y, int z = x + y); // expected-error {{default argument references parameter 'x'}} expected-error {{default argument references parameter 'y'}}