[cfe-commits] r49370 - /cfe/trunk/lib/Sema/SemaDeclCXX.cpp
Chris Lattner
sabre at nondot.org
Mon Apr 7 22:04:31 PDT 2008
Author: lattner
Date: Tue Apr 8 00:04:30 2008
New Revision: 49370
URL: http://llvm.org/viewvc/llvm-project?rev=49370&view=rev
Log:
Add support for C++ default arguments, and rework Parse-Sema
interaction for function parameters, fixing PR2046.
Patch by Doug Gregor!
Added:
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
Added: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=49370&view=auto
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (added)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Apr 8 00:04:30 2008
@@ -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);
+ }
+ }
+ }
+}
More information about the cfe-commits
mailing list