forked from OSchip/llvm-project
Add support for C++ default arguments, and rework Parse-Sema
interaction for function parameters, fixing PR2046. Patch by Doug Gregor! llvm-svn: 49370
This commit is contained in:
parent
aa9c7aed0f
commit
199abbcb26
|
@ -0,0 +1,158 @@
|
|||
//===------ SemaDeclCXX.cpp - Semantic Analysis for C++ Declarations ------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements semantic analysis for C++ declarations.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Sema.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
void
|
||||
Sema::ActOnParamDefaultArgument(DeclTy *param, SourceLocation EqualLoc,
|
||||
ExprTy *defarg) {
|
||||
ParmVarDecl *Param = (ParmVarDecl *)param;
|
||||
llvm::OwningPtr<Expr> DefaultArg((Expr *)defarg);
|
||||
QualType ParamType = Param->getType();
|
||||
|
||||
// Default arguments are only permitted in C++
|
||||
if (!getLangOptions().CPlusPlus) {
|
||||
Diag(EqualLoc, diag::err_param_default_argument,
|
||||
DefaultArg->getSourceRange());
|
||||
return;
|
||||
}
|
||||
|
||||
// C++ [dcl.fct.default]p5
|
||||
// A default argument expression is implicitly converted (clause
|
||||
// 4) to the parameter type. The default argument expression has
|
||||
// the same semantic constraints as the initializer expression in
|
||||
// a declaration of a variable of the parameter type, using the
|
||||
// copy-initialization semantics (8.5).
|
||||
//
|
||||
// FIXME: CheckSingleAssignmentConstraints has the wrong semantics
|
||||
// for C++ (since we want copy-initialization, not copy-assignment),
|
||||
// but we don't have the right semantics implemented yet. Because of
|
||||
// this, our error message is also very poor.
|
||||
QualType DefaultArgType = DefaultArg->getType();
|
||||
Expr *DefaultArgPtr = DefaultArg.get();
|
||||
AssignConvertType ConvTy = CheckSingleAssignmentConstraints(ParamType,
|
||||
DefaultArgPtr);
|
||||
if (DefaultArgPtr != DefaultArg.get()) {
|
||||
DefaultArg.take();
|
||||
DefaultArg.reset(DefaultArgPtr);
|
||||
}
|
||||
if (DiagnoseAssignmentResult(ConvTy, DefaultArg->getLocStart(),
|
||||
ParamType, DefaultArgType, DefaultArg.get(),
|
||||
"in default argument")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: C++ [dcl.fct.default]p3
|
||||
// A default argument expression shall be specified only in the
|
||||
// parameter-declaration-clause of a function declaration or in a
|
||||
// template-parameter (14.1). It shall not be specified for a
|
||||
// parameter pack. If it is specified in a
|
||||
// parameter-declaration-clause, it shall not occur within a
|
||||
// declarator or abstract-declarator of a parameter-declaration.
|
||||
|
||||
// Okay: add the default argument to the parameter
|
||||
Param->setDefaultArg(DefaultArg.take());
|
||||
}
|
||||
|
||||
// MergeCXXFunctionDecl - Merge two declarations of the same C++
|
||||
// function, once we already know that they have the same
|
||||
// type. Subroutine of MergeFunctionDecl.
|
||||
FunctionDecl *
|
||||
Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
|
||||
// C++ [dcl.fct.default]p4:
|
||||
//
|
||||
// For non-template functions, default arguments can be added in
|
||||
// later declarations of a function in the same
|
||||
// scope. Declarations in different scopes have completely
|
||||
// distinct sets of default arguments. That is, declarations in
|
||||
// inner scopes do not acquire default arguments from
|
||||
// declarations in outer scopes, and vice versa. In a given
|
||||
// function declaration, all parameters subsequent to a
|
||||
// parameter with a default argument shall have default
|
||||
// arguments supplied in this or previous declarations. A
|
||||
// default argument shall not be redefined by a later
|
||||
// declaration (not even to the same value).
|
||||
for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) {
|
||||
ParmVarDecl *OldParam = Old->getParamDecl(p);
|
||||
ParmVarDecl *NewParam = New->getParamDecl(p);
|
||||
|
||||
if(OldParam->getDefaultArg() && NewParam->getDefaultArg()) {
|
||||
Diag(NewParam->getLocation(),
|
||||
diag::err_param_default_argument_redefinition,
|
||||
NewParam->getDefaultArg()->getSourceRange());
|
||||
Diag(OldParam->getLocation(), diag::err_previous_definition);
|
||||
} else if (OldParam->getDefaultArg()) {
|
||||
// Merge the old default argument into the new parameter
|
||||
NewParam->setDefaultArg(OldParam->getDefaultArg());
|
||||
}
|
||||
}
|
||||
|
||||
return New;
|
||||
}
|
||||
|
||||
/// CheckCXXDefaultArguments - Verify that the default arguments for a
|
||||
/// function declaration are well-formed according to C++
|
||||
/// [dcl.fct.default].
|
||||
void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) {
|
||||
unsigned NumParams = FD->getNumParams();
|
||||
unsigned p;
|
||||
|
||||
// Find first parameter with a default argument
|
||||
for (p = 0; p < NumParams; ++p) {
|
||||
ParmVarDecl *Param = FD->getParamDecl(p);
|
||||
if (Param->getDefaultArg())
|
||||
break;
|
||||
}
|
||||
|
||||
// C++ [dcl.fct.default]p4:
|
||||
// In a given function declaration, all parameters
|
||||
// subsequent to a parameter with a default argument shall
|
||||
// have default arguments supplied in this or previous
|
||||
// declarations. A default argument shall not be redefined
|
||||
// by a later declaration (not even to the same value).
|
||||
unsigned LastMissingDefaultArg = 0;
|
||||
for(; p < NumParams; ++p) {
|
||||
ParmVarDecl *Param = FD->getParamDecl(p);
|
||||
if (!Param->getDefaultArg()) {
|
||||
if (Param->getIdentifier())
|
||||
Diag(Param->getLocation(),
|
||||
diag::err_param_default_argument_missing_name,
|
||||
Param->getIdentifier()->getName());
|
||||
else
|
||||
Diag(Param->getLocation(),
|
||||
diag::err_param_default_argument_missing);
|
||||
|
||||
LastMissingDefaultArg = p;
|
||||
}
|
||||
}
|
||||
|
||||
if (LastMissingDefaultArg > 0) {
|
||||
// Some default arguments were missing. Clear out all of the
|
||||
// default arguments up to (and including) the last missing
|
||||
// default argument, so that we leave the function parameters
|
||||
// in a semantically valid state.
|
||||
for (p = 0; p <= LastMissingDefaultArg; ++p) {
|
||||
ParmVarDecl *Param = FD->getParamDecl(p);
|
||||
if (Param->getDefaultArg()) {
|
||||
delete Param->getDefaultArg();
|
||||
Param->setDefaultArg(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue