diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-12-24 00:01:03 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-12-24 00:01:03 +0000 |
commit | 583540360c39e5512edefb667d9e7f3da91d8720 (patch) | |
tree | 94fa0ff5032daa72302885df09a0154b094bdd63 /clang/lib/Sema/SemaDeclCXX.cpp | |
parent | ee573fcefc55ca4c672d2991145ada28ee584651 (diff) | |
download | bcm5719-llvm-583540360c39e5512edefb667d9e7f3da91d8720.tar.gz bcm5719-llvm-583540360c39e5512edefb667d9e7f3da91d8720.zip |
Correct the order in which we cope with end-of-class-definition
semantics and improve our handling of default arguments. Specifically,
we follow this order:
- As soon as the see the '}' in the class definition, the class is
complete and we add any implicit declarations (default constructor,
copy constructor, etc.) to the class.
- If there are any default function arguments, parse them
- If there were any inline member function definitions, parse them
As part of this change, we now keep track of the the fact that we've
seen unparsed default function arguments within the AST. See the new
ParmVarDecl::hasUnparsedDefaultArg member. This allows us to properly
cope with calls inside default function arguments to other functions
where we're making use of the default arguments.
Made some C++ error messages regarding failed initializations more
specific.
llvm-svn: 61406
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 918fd2ac9a7..48373369bcf 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -126,8 +126,9 @@ Sema::ActOnParamDefaultArgument(DeclTy *param, SourceLocation EqualLoc, // a declaration of a variable of the parameter type, using the // copy-initialization semantics (8.5). Expr *DefaultArgPtr = DefaultArg.get(); - bool DefaultInitFailed = PerformCopyInitialization(DefaultArgPtr, ParamType, - "in default argument"); + bool DefaultInitFailed = CheckInitializerTypes(DefaultArgPtr, ParamType, + EqualLoc, + Param->getDeclName()); if (DefaultArgPtr != DefaultArg.get()) { DefaultArg.take(); DefaultArg.reset(DefaultArgPtr); @@ -147,6 +148,17 @@ Sema::ActOnParamDefaultArgument(DeclTy *param, SourceLocation EqualLoc, Param->setDefaultArg(DefaultArg.take()); } +/// ActOnParamUnparsedDefaultArgument - We've seen a default +/// argument for a function parameter, but we can't parse it yet +/// because we're inside a class definition. Note that this default +/// argument will be parsed later. +void Sema::ActOnParamUnparsedDefaultArgument(DeclTy *param, + SourceLocation EqualLoc) { + ParmVarDecl *Param = (ParmVarDecl*)param; + if (Param) + Param->setUnparsedDefaultArg(); +} + /// ActOnParamDefaultArgumentError - Parsing or semantic analysis of /// the default argument for the parameter param failed. void Sema::ActOnParamDefaultArgumentError(DeclTy *param) { @@ -171,16 +183,16 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { if (chunk.Kind == DeclaratorChunk::Function) { for (unsigned argIdx = 0; argIdx < chunk.Fun.NumArgs; ++argIdx) { ParmVarDecl *Param = (ParmVarDecl *)chunk.Fun.ArgInfo[argIdx].Param; - if (Param->getDefaultArg()) { - Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) - << Param->getDefaultArg()->getSourceRange(); - Param->setDefaultArg(0); - } else if (CachedTokens *Toks - = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens) { + if (Param->hasUnparsedDefaultArg()) { + CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens; Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) << SourceRange((*Toks)[1].getLocation(), Toks->back().getLocation()); delete Toks; chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0; + } else if (Param->getDefaultArg()) { + Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) + << Param->getDefaultArg()->getSourceRange(); + Param->setDefaultArg(0); } } } @@ -269,7 +281,8 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { for (p = 0; p <= LastMissingDefaultArg; ++p) { ParmVarDecl *Param = FD->getParamDecl(p); if (Param->getDefaultArg()) { - delete Param->getDefaultArg(); + if (!Param->hasUnparsedDefaultArg()) + Param->getDefaultArg()->Destroy(Context); Param->setDefaultArg(0); } } @@ -736,6 +749,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, ActOnFields(S, RLoc, TagDecl, (DeclTy**)FieldCollector->getCurFields(), FieldCollector->getCurNumFields(), LBrac, RBrac, 0); + AddImplicitlyDeclaredMembersToClass(cast<CXXRecordDecl>((Decl*)TagDecl)); } /// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared @@ -872,7 +886,6 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { void Sema::ActOnFinishCXXClassDef(DeclTy *D) { CXXRecordDecl *Rec = cast<CXXRecordDecl>(static_cast<Decl *>(D)); FieldCollector->FinishClass(); - AddImplicitlyDeclaredMembersToClass(Rec); PopDeclContext(); // Everything, including inline method definitions, have been parsed. @@ -901,6 +914,12 @@ void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclTy *Method) { /// ActOnParamDefaultArgument event for this parameter. void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclTy *ParamD) { ParmVarDecl *Param = (ParmVarDecl*)ParamD; + + // If this parameter has an unparsed default argument, clear it out + // to make way for the parsed default argument. + if (Param->hasUnparsedDefaultArg()) + Param->setDefaultArg(0); + S->AddDecl(Param); if (Param->getDeclName()) IdResolver.AddDecl(Param); @@ -1871,7 +1890,11 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { if (Op != OO_Call) { for (FunctionDecl::param_iterator Param = FnDecl->param_begin(); Param != FnDecl->param_end(); ++Param) { - if (Expr *DefArg = (*Param)->getDefaultArg()) + if ((*Param)->hasUnparsedDefaultArg()) + return Diag((*Param)->getLocation(), + diag::err_operator_overload_default_arg) + << FnDecl->getDeclName(); + else if (Expr *DefArg = (*Param)->getDefaultArg()) return Diag((*Param)->getLocation(), diag::err_operator_overload_default_arg) << FnDecl->getDeclName() << DefArg->getSourceRange(); |