aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-04-08 04:40:51 +0000
committerChris Lattner <sabre@nondot.org>2008-04-08 04:40:51 +0000
commit04421087832a031c90bd58f128c7c0e741db8dd2 (patch)
treec80c38dcc7ecb4d31cf5c10faa49e00fc373ea81
parent5db17c9b5edb43e12196e565389b73e91a4fcb65 (diff)
Add support for C++ default arguments, and rework Parse-Sema
interaction for function parameters, fixing PR2046. Patch by Doug Gregor! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49369 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--Driver/clang.cpp9
-rw-r--r--include/clang/AST/Decl.h15
-rw-r--r--include/clang/AST/ExprCXX.h39
-rw-r--r--include/clang/AST/StmtNodes.def1
-rw-r--r--include/clang/Basic/DiagnosticKinds.def12
-rw-r--r--include/clang/Parse/Action.h19
-rw-r--r--include/clang/Parse/DeclSpec.h10
-rw-r--r--lib/AST/Decl.cpp4
-rw-r--r--lib/AST/DeclSerialization.cpp5
-rw-r--r--lib/AST/Expr.cpp15
-rw-r--r--lib/AST/ExprCXX.cpp8
-rw-r--r--lib/AST/StmtPrinter.cpp9
-rw-r--r--lib/AST/StmtSerialization.cpp21
-rw-r--r--lib/CodeGen/CGExprAgg.cpp3
-rw-r--r--lib/CodeGen/CGExprComplex.cpp3
-rw-r--r--lib/CodeGen/CGExprConstant.cpp4
-rw-r--r--lib/CodeGen/CGExprScalar.cpp5
-rw-r--r--lib/Parse/ParseDecl.cpp52
-rw-r--r--lib/Parse/Parser.cpp17
-rw-r--r--lib/Sema/Sema.h15
-rw-r--r--lib/Sema/SemaDecl.cpp224
-rw-r--r--lib/Sema/SemaDeclObjC.cpp31
-rw-r--r--lib/Sema/SemaExpr.cpp53
-rw-r--r--lib/Sema/SemaType.cpp39
-rw-r--r--test/CodeGen/cxx-default-arg.cpp25
-rw-r--r--test/Sema/arg-scope-c99.c2
-rw-r--r--test/Sema/arg-scope.c5
-rw-r--r--test/Sema/default1.c2
-rw-r--r--test/Sema/default1.cpp17
-rw-r--r--test/Sema/default2.cpp12
30 files changed, 498 insertions, 178 deletions
diff --git a/Driver/clang.cpp b/Driver/clang.cpp
index 397c27db54..6c82f19572 100644
--- a/Driver/clang.cpp
+++ b/Driver/clang.cpp
@@ -901,6 +901,11 @@ static void InitializeIncludePaths(const char *Argv0, HeaderSearch &Headers,
false, Headers);
AddPath("/usr/include/c++/4.1.3/backward", System, true, false, false,
Headers);
+
+ // Fedora 8
+ AddPath("/usr/include/c++/4.1.2", System, true, false, false, Headers);
+ AddPath("/usr/include/c++/4.1.2/i386-redhat-linux", System, true, false, false, Headers);
+ AddPath("/usr/include/c++/4.1.2/backward", System, true, false, false, Headers);
}
AddPath("/usr/local/include", System, false, false, false, Headers);
@@ -926,6 +931,10 @@ static void InitializeIncludePaths(const char *Argv0, HeaderSearch &Headers,
AddPath("/usr/lib/gcc/i486-linux-gnu/4.1.3/include", System,
false, false, false, Headers);
+ // Fedora 8
+ AddPath("/usr/lib/gcc/i386-redhat-linux/4.1.2/include", System,
+ false, false, false, Headers);
+
//Debian testing/lenny x86
AddPath("/usr/lib/gcc/i486-linux-gnu/4.2.3/include", System,
false, false, false, Headers);
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 3bae5e2d4c..bce65f9b57 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -246,15 +246,20 @@ class ParmVarDecl : public VarDecl {
/// in, inout, etc.
unsigned objcDeclQualifier : 6;
+ /// Default argument, if any. [C++ Only]
+ Expr *DefaultArg;
+
ParmVarDecl(DeclContext *CD, SourceLocation L,
IdentifierInfo *Id, QualType T, StorageClass S,
- ScopedDecl *PrevDecl)
+ Expr *DefArg, ScopedDecl *PrevDecl)
: VarDecl(ParmVar, CD, L, Id, T, S, PrevDecl),
- objcDeclQualifier(OBJC_TQ_None) {}
+ objcDeclQualifier(OBJC_TQ_None), DefaultArg(DefArg) {}
+
public:
static ParmVarDecl *Create(ASTContext &C, DeclContext *CD,
SourceLocation L,IdentifierInfo *Id,
- QualType T, StorageClass S, ScopedDecl *PrevDecl);
+ QualType T, StorageClass S, Expr *DefArg,
+ ScopedDecl *PrevDecl);
ObjCDeclQualifier getObjCDeclQualifier() const {
return ObjCDeclQualifier(objcDeclQualifier);
@@ -262,6 +267,10 @@ public:
void setObjCDeclQualifier(ObjCDeclQualifier QTVal)
{ objcDeclQualifier = QTVal; }
+ const Expr *getDefaultArg() const { return DefaultArg; }
+ Expr *getDefaultArg() { return DefaultArg; }
+ void setDefaultArg(Expr *defarg) { DefaultArg = defarg; }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == ParmVar; }
static bool classof(const ParmVarDecl *D) { return true; }
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 357fb9538f..3c99321a8a 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -127,6 +127,45 @@ namespace clang {
virtual child_iterator child_end();
};
+ /// CXXDefaultArgExpr - C++ [dcl.fct.default]. This wraps up a
+ /// function call argument that was created from the corresponding
+ /// parameter's default argument, when the call did not explicitly
+ /// supply arguments for all of the parameters.
+ class CXXDefaultArgExpr : public Expr {
+ ParmVarDecl *Param;
+ public:
+ // Param is the parameter whose default argument is used by this
+ // expression.
+ explicit CXXDefaultArgExpr(ParmVarDecl *param)
+ : Expr(CXXDefaultArgExprClass, param->getDefaultArg()->getType()),
+ Param(param) { }
+
+ // Retrieve the parameter that the argument was created from.
+ const ParmVarDecl *getParam() const { return Param; }
+ ParmVarDecl *getParam() { return Param; }
+
+ // Retrieve the actual argument to the function call.
+ const Expr *getExpr() const { return Param->getDefaultArg(); }
+ Expr *getExpr() { return Param->getDefaultArg(); }
+
+ virtual SourceRange getSourceRange() const {
+ return Param->getDefaultArg()->getSourceRange();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDefaultArgExprClass;
+ }
+ static bool classof(const CXXDefaultArgExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+
+ // Serialization
+ virtual void EmitImpl(llvm::Serializer& S) const;
+ static CXXDefaultArgExpr* CreateImpl(llvm::Deserializer& D,
+ ASTContext& C);
+ };
} // end namespace clang
#endif
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
index 4c0fd7a242..e3f0273308 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -91,6 +91,7 @@ STMT(58, ChooseExpr , Expr)
STMT(60, CXXCastExpr , Expr)
STMT(61, CXXBoolLiteralExpr , Expr)
STMT(62, CXXThrowExpr , Expr)
+STMT(63, CXXDefaultArgExpr , Expr)
// Obj-C Expressions.
STMT(70, ObjCStringLiteral , Expr)
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index 1de1b6b80f..611edf51f5 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -243,7 +243,6 @@ DIAG(err_pp_I_dash_not_supported, ERROR,
//===----------------------------------------------------------------------===//
// Parser Diagnostics
//===----------------------------------------------------------------------===//
-
DIAG(w_type_defaults_to_int, WARNING,
"type defaults to 'int'")
DIAG(w_no_declarators, WARNING,
@@ -314,7 +313,7 @@ DIAG(ext_gnu_old_style_field_designator, EXTENSION,
"use of GNU old-style field designator extension")
DIAG(ext_gnu_case_range, EXTENSION,
"use of GNU case range extension")
-
+
// Generic errors.
DIAG(err_parse_error, ERROR,
"parse error")
@@ -621,7 +620,14 @@ DIAG(err_no_matching_param, ERROR,
"parameter named '%0' is missing")
DIAG(ext_param_not_declared, EXTENSION,
"parameter '%0' was not declared, defaulting to type 'int'")
-
+DIAG(err_param_default_argument, ERROR,
+ "C does not support default arguments")
+DIAG(err_param_default_argument_redefinition, ERROR,
+ "redefinition of default argument")
+DIAG(err_param_default_argument_missing, ERROR,
+ "missing default argument on parameter")
+DIAG(err_param_default_argument_missing_name, ERROR,
+ "missing default argument on parameter '%0'")
DIAG(err_previous_definition, ERROR,
"previous definition is here")
DIAG(err_previous_use, ERROR,
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 83d1fea715..fb180c2d1a 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -107,6 +107,14 @@ public:
return 0;
}
+ /// ActOnParamDeclarator - This callback is invoked when a parameter
+ /// declarator is parsed. This callback only occurs for functions
+ /// with prototypes. S is the function prototype scope for the
+ /// parameters (C++ [basic.scope.proto]).
+ virtual DeclTy *ActOnParamDeclarator(Scope *S, Declarator &D) {
+ return 0;
+ }
+
/// AddInitializerToDecl - This action is called immediately after
/// ParseDeclarator (when an initializer is present). The code is factored
/// this way to make sure we are able to handle the following:
@@ -173,10 +181,6 @@ public:
return 0;
}
- virtual TypeResult ActOnParamDeclaratorType(Scope *S, Declarator &D) {
- return 0;
- }
-
enum TagKind {
TK_Reference, // Reference to a tag: 'struct foo *X;'
TK_Declaration, // Fwd decl of a tag: 'struct foo;'
@@ -503,6 +507,13 @@ public:
SourceLocation RPLoc) {
return 0;
}
+
+ //===------------------------- C++ Declarations -------------------------===//
+ /// ActOnParamDefaultArgument - Parse default argument for function parameter
+ virtual void ActOnParamDefaultArgument(DeclTy *param,
+ SourceLocation EqualLoc,
+ ExprTy *defarg) {
+ }
//===------------------------- C++ Expressions --------------------------===//
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h
index e52f307e6e..6204a383b9 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Parse/DeclSpec.h
@@ -416,14 +416,10 @@ struct DeclaratorChunk {
struct ParamInfo {
IdentifierInfo *Ident;
SourceLocation IdentLoc;
- Action::TypeTy *TypeInfo;
- bool InvalidType;
- AttributeList *AttrList;
+ Action::DeclTy *Param;
ParamInfo() {}
- ParamInfo(IdentifierInfo *ident, SourceLocation iloc, Action::TypeTy *typ,
- bool flag = false, AttributeList *AL = 0)
- : Ident(ident), IdentLoc(iloc), TypeInfo(typ), InvalidType(flag),
- AttrList(AL) {}
+ ParamInfo(IdentifierInfo *ident, SourceLocation iloc, Action::DeclTy *param)
+ : Ident(ident), IdentLoc(iloc), Param(param) {}
};
struct FunctionTypeInfo {
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index e27015b7ef..8228eceebf 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -224,9 +224,9 @@ FileVarDecl *FileVarDecl::Create(ASTContext &C, DeclContext *CD,
ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *CD,
SourceLocation L, IdentifierInfo *Id,
QualType T, StorageClass S,
- ScopedDecl *PrevDecl) {
+ Expr *DefArg, ScopedDecl *PrevDecl) {
void *Mem = C.getAllocator().Allocate<ParmVarDecl>();
- return new (Mem) ParmVarDecl(CD, L, Id, T, S, PrevDecl);
+ return new (Mem) ParmVarDecl(CD, L, Id, T, S, DefArg, PrevDecl);
}
FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *CD,
diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index bc5310c414..14666d6f00 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -226,15 +226,16 @@ FileVarDecl* FileVarDecl::CreateImpl(Deserializer& D, ASTContext& C) {
void ParmVarDecl::EmitImpl(llvm::Serializer& S) const {
VarDecl::EmitImpl(S);
S.EmitInt(getObjCDeclQualifier()); // From ParmVarDecl.
+ S.EmitOwnedPtr(getDefaultArg()); // From ParmVarDecl.
}
ParmVarDecl* ParmVarDecl::CreateImpl(Deserializer& D, ASTContext& C) {
ParmVarDecl* decl =
- new ParmVarDecl(0, SourceLocation(),NULL,QualType(),None,NULL);
+ new ParmVarDecl(0, SourceLocation(), NULL, QualType(), None, NULL, NULL);
decl->VarDecl::ReadImpl(D, C);
decl->objcDeclQualifier = static_cast<ObjCDeclQualifier>(D.ReadInt());
-
+ decl->DefaultArg = D.ReadOwnedPtr<Expr>(C);
return decl;
}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 5205702f29..0287aa0831 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -337,6 +337,9 @@ bool Expr::hasLocalSideEffect() const {
if (getType()->isVoidType())
return cast<CastExpr>(this)->getSubExpr()->hasLocalSideEffect();
return false;
+
+ case CXXDefaultArgExprClass:
+ return cast<CXXDefaultArgExpr>(this)->getExpr()->hasLocalSideEffect();
}
}
@@ -401,6 +404,8 @@ Expr::isLvalueResult Expr::isLvalue() const {
return LV_Valid;
case PreDefinedExprClass:
return LV_Valid;
+ case CXXDefaultArgExprClass:
+ return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue();
default:
break;
}
@@ -465,6 +470,8 @@ bool Expr::hasGlobalStorage() const {
return cast<ArraySubscriptExpr>(this)->getBase()->hasGlobalStorage();
case PreDefinedExprClass:
return true;
+ case CXXDefaultArgExprClass:
+ return cast<CXXDefaultArgExpr>(this)->getExpr()->hasGlobalStorage();
}
}
@@ -636,6 +643,8 @@ bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
}
return true;
}
+ case CXXDefaultArgExprClass:
+ return cast<CXXDefaultArgExpr>(this)->getExpr()->isConstantExpr(Ctx, Loc);
}
}
@@ -981,6 +990,9 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
return false;
break;
}
+ case CXXDefaultArgExprClass:
+ return cast<CXXDefaultArgExpr>(this)
+ ->isIntegerConstantExpr(Result, Ctx, Loc, isEvaluated);
}
// Cases that are valid constant exprs fall through to here.
@@ -1009,6 +1021,9 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx) const {
// Accept ((void*)0) as a null pointer constant, as many other
// implementations do.
return PE->getSubExpr()->isNullPointerConstant(Ctx);
+ } else if (const CXXDefaultArgExpr *DefaultArg = dyn_cast<CXXDefaultArgExpr>(this)) {
+ // See through default argument expressions
+ return DefaultArg->getExpr()->isNullPointerConstant(Ctx);
}
// This expression must be an integer type.
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 3bc32e75d8..03faf8b8b5 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -45,3 +45,11 @@ Stmt::child_iterator CXXThrowExpr::child_end() {
return reinterpret_cast<Stmt**>(&Op)+0;
return reinterpret_cast<Stmt**>(&Op)+1;
}
+
+// CXXDefaultArgExpr
+Stmt::child_iterator CXXDefaultArgExpr::child_begin() {
+ return reinterpret_cast<Stmt**>(Param->getDefaultArg());
+}
+Stmt::child_iterator CXXDefaultArgExpr::child_end() {
+ return reinterpret_cast<Stmt**>(Param->getDefaultArg())+1;
+}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index ba82b7fcff..a76fd1f9b5 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -658,6 +658,11 @@ void StmtPrinter::VisitCallExpr(CallExpr *Call) {
PrintExpr(Call->getCallee());
OS << "(";
for (unsigned i = 0, e = Call->getNumArgs(); i != e; ++i) {
+ if (isa<CXXDefaultArgExpr>(Call->getArg(i))) {
+ // Don't print any defaulted arguments
+ break;
+ }
+
if (i) OS << ", ";
PrintExpr(Call->getArg(i));
}
@@ -789,6 +794,10 @@ void StmtPrinter::VisitCXXThrowExpr(CXXThrowExpr *Node) {
}
}
+void StmtPrinter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Node) {
+ // Nothing to print: we picked up the default argument
+}
+
// Obj-C
void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp
index 41569df8f2..7058c0ce2f 100644
--- a/lib/AST/StmtSerialization.cpp
+++ b/lib/AST/StmtSerialization.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "llvm/Bitcode/Serialize.h"
#include "llvm/Bitcode/Deserialize.h"
@@ -185,6 +186,13 @@ Stmt* Stmt::Create(Deserializer& D, ASTContext& C) {
case ObjCStringLiteralClass:
return ObjCStringLiteral::CreateImpl(D, C);
+
+ //==--------------------------------------==//
+ // C++
+ //==--------------------------------------==//
+ case CXXDefaultArgExprClass:
+ return CXXDefaultArgExpr::CreateImpl(D, C);
+
}
}
@@ -1002,3 +1010,16 @@ ObjCStringLiteral* ObjCStringLiteral::CreateImpl(Deserializer& D, ASTContext& C)
StringLiteral* String = cast<StringLiteral>(D.ReadOwnedPtr<Stmt>(C));
return new ObjCStringLiteral(String,T,L);
}
+
+//===----------------------------------------------------------------------===//
+// C++ Serialization
+//===----------------------------------------------------------------------===//
+void CXXDefaultArgExpr::EmitImpl(Serializer& S) const {
+ S.EmitPtr(Param);
+}
+
+CXXDefaultArgExpr *CXXDefaultArgExpr::CreateImpl(Deserializer& D, ASTContext& C) {
+ ParmVarDecl* Param = 0;
+ D.ReadPtr(Param, false);
+ return new CXXDefaultArgExpr(Param);
+}
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 3bfcc10f7f..b5c755a582 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -86,6 +86,9 @@ public:
void VisitConditionalOperator(const ConditionalOperator *CO);
void VisitInitListExpr(InitListExpr *E);
+ void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
+ Visit(DAE->getExpr());
+ }
void EmitInitializationToLValue(Expr *E, LValue Address);
void EmitNullInitializationToLValue(LValue Address, QualType T);
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index 1e8c8a37f2..a486d6ae15 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -120,6 +120,9 @@ public:
ComplexPairTy VisitUnaryExtension(const UnaryOperator *E) {
return Visit(E->getSubExpr());
}
+ ComplexPairTy VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
+ return Visit(DAE->getExpr());
+ }
struct BinOpInfo {
ComplexPairTy LHS;
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index e2405b88f3..2ca71c3153 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -69,6 +69,10 @@ public:
return EmitConversion(C, E->getSubExpr()->getType(), E->getType());
}
+ llvm::Constant *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
+ return Visit(DAE->getExpr());
+ }
+
llvm::Constant *EmitArrayInitialization(InitListExpr *ILE,
const llvm::ArrayType *AType) {
std::vector<llvm::Constant*> Elts;
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 89779075a4..2f03f88ebf 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -169,7 +169,7 @@ public:
Value *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
return Visit(E->getInitializer());
}
-
+
Value *VisitImplicitCastExpr(const ImplicitCastExpr *E);
Value *VisitCastExpr(const CastExpr *E) {
return EmitCastExpr(E->getSubExpr(), E->getType());
@@ -220,6 +220,9 @@ public:
return Visit(E->getSubExpr());
}
Value *VisitUnaryOffsetOf(const UnaryOperator *E);
+ Value *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
+ return Visit(DAE->getExpr());
+ }
// Binary Operators.
Value *EmitMul(const BinOpInfo &Ops) {
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 0eb5c1f257..0eb95fa908 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1232,8 +1232,10 @@ void Parser::ParseParenDeclarator(Declarator &D) {
///
/// parameter-declaration: [C99 6.7.5]
/// declaration-specifiers declarator
+/// [C++] declaration-specifiers declarator '=' assignment-expression
/// [GNU] declaration-specifiers declarator attributes
/// declaration-specifiers abstract-declarator[opt]
+/// [C++] declaration-specifiers abstract-declarator[opt] '=' assignment-expression
/// [GNU] declaration-specifiers abstract-declarator[opt] attributes
///
void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D) {
@@ -1265,11 +1267,9 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D) {
// Build up an array of information about the parsed arguments.
llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
- llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;
-
- // Enter function-declaration scope, limiting any declarators for struct
- // tags to the function prototype scope.
- // FIXME: is this needed?
+
+ // Enter function-declaration scope, limiting any declarators to the
+ // function prototype scope, including parameter declarators.
EnterScope(Scope::DeclScope);
bool IsVariadic = false;
@@ -1307,14 +1307,6 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D) {
// Remember this parsed parameter in ParamInfo.
IdentifierInfo *ParmII = ParmDecl.getIdentifier();
- // Verify that the argument identifier has not already been mentioned.
- if (ParmII && !ParamsSoFar.insert(ParmII)) {
- Diag(ParmDecl.getIdentifierLoc(), diag::err_param_redefinition,
- ParmII->getName());
- ParmII = 0;
- ParmDecl.setInvalidType(true);
- }
-
// If no parameter was specified, verify that *something* was specified,
// otherwise we have a missing type and identifier.
if (DS.getParsedSpecifiers() == DeclSpec::PQ_None &&
@@ -1327,12 +1319,37 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D) {
// Inform the actions module about the parameter declarator, so it gets
// added to the current scope.
- Action::TypeResult ParamTy =
- Actions.ActOnParamDeclaratorType(CurScope, ParmDecl);
+ DeclTy *Param = Actions.ActOnParamDeclarator(CurScope, ParmDecl);
+
+ // Parse the default argument, if any. We parse the default
+ // arguments in all dialects; the semantic analysis in
+ // ActOnParamDefaultArgument will reject the default argument in
+ // C.
+ if (Tok.is(tok::equal)) {
+ SourceLocation EqualLoc = Tok.getLocation();
+
+ // Consume the '='.
+ 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);
+ } else {
+ // Inform the actions module about the default argument
+ Actions.ActOnParamDefaultArgument(Param, EqualLoc, DefArgResult.Val);
+ }
+ }
ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
- ParmDecl.getIdentifierLoc(), ParamTy.Val, ParmDecl.getInvalidType(),
- ParmDecl.getDeclSpec().TakeAttributes()));
+ ParmDecl.getIdentifierLoc(), Param));
}
// If the next token is a comma, consume it and keep reading arguments.
@@ -1354,7 +1371,6 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D) {
MatchRHSPunctuation(tok::r_paren, LParenLoc);
}
-
/// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
/// we found a K&R-style identifier list instead of a type argument list. The
/// current token is known to be the first identifier in the list.
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index cd99fc04eb..7e41bcc92e 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -509,6 +509,10 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
// We know that the top-level of this declarator is a function.
DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+ // Enter function-declaration scope, limiting any declarators to the
+ // function prototype scope, including parameter declarators.
+ EnterScope(Scope::DeclScope);
+
// Read all the argument declarations.
while (isDeclarationSpecifier()) {
SourceLocation DSStart = Tok.getLocation();
@@ -555,10 +559,10 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
AttrList = ParseAttributes();
// Ask the actions module to compute the type for this declarator.
- Action::TypeResult TR =
- Actions.ActOnParamDeclaratorType(CurScope, ParmDeclarator);
+ Action::DeclTy *Param =
+ Actions.ActOnParamDeclarator(CurScope, ParmDeclarator);
- if (!TR.isInvalid &&
+ if (Param &&
// A missing identifier has already been diagnosed.
ParmDeclarator.getIdentifier()) {
@@ -575,12 +579,12 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
if (FTI.ArgInfo[i].Ident == ParmDeclarator.getIdentifier()) {
// Reject redefinitions of parameters.
- if (FTI.ArgInfo[i].TypeInfo) {
+ if (FTI.ArgInfo[i].Param) {
Diag(ParmDeclarator.getIdentifierLoc(),
diag::err_param_redefinition,
ParmDeclarator.getIdentifier()->getName());
} else {
- FTI.ArgInfo[i].TypeInfo = TR.Val;
+ FTI.ArgInfo[i].Param = Param;
}
break;
}
@@ -611,6 +615,9 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
}
}
+ // Leave prototype scope.
+ ExitScope();
+
// The actions module must verify that all arguments were declared.
}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 70aaf24791..b2a88eb635 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -202,14 +202,16 @@ public:
virtual TypeResult ActOnTypeName(Scope *S, Declarator &D);
-
- virtual TypeResult ActOnParamDeclaratorType(Scope *S, Declarator &D);
private:
//===--------------------------------------------------------------------===//
// Symbol table / Decl tracking callbacks: SemaDecl.cpp.
//
virtual DeclTy *isTypeName(const IdentifierInfo &II, Scope *S);
virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup);
+ virtual DeclTy *ActOnParamDeclarator(Scope *S, Declarator &D);
+ virtual void ActOnParamDefaultArgument(DeclTy *param,
+ SourceLocation EqualLoc,
+ ExprTy *defarg);
void AddInitializerToDecl(DeclTy *dcl, ExprTy *init);
virtual DeclTy *FinalizeDeclaratorGroup(Scope *S, DeclTy *Group);
@@ -259,10 +261,15 @@ private:
TypedefDecl *MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
FunctionDecl *MergeFunctionDecl(FunctionDecl *New, Decl *Old);
VarDecl *MergeVarDecl(VarDecl *New, Decl *Old);
+ FunctionDecl *MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
+
+ /// Helpers for dealing with function parameters
+ bool CheckParmsForFunctionDef(FunctionDecl *FD);
+ ParmVarDecl *CreateImplicitParameter(Scope *S, IdentifierInfo *Id,
+ SourceLocation IdLoc, QualType Type);
+ void CheckCXXDefaultArguments(FunctionDecl *FD);
/// More parsing and symbol table subroutines...
- ParmVarDecl *ActOnParamDeclarator(struct DeclaratorChunk::ParamInfo &PI,
- Scope *FnBodyScope);
Decl *LookupDecl(const IdentifierInfo *II, unsigned NSI, Scope *S,
bool enableLazyBuiltinCreation = true);
ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 0f464a0bc7..5451ec27c0 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -263,9 +263,10 @@ static