2008-04-08 13:04:30 +08:00
|
|
|
|
//===------ 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"
|
2008-11-05 12:29:56 +08:00
|
|
|
|
#include "SemaInherit.h"
|
2008-08-09 08:58:37 +08:00
|
|
|
|
#include "clang/AST/ASTConsumer.h"
|
2008-04-14 05:30:24 +08:00
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2009-03-24 09:19:16 +08:00
|
|
|
|
#include "clang/AST/DeclVisitor.h"
|
2008-10-23 05:13:31 +08:00
|
|
|
|
#include "clang/AST/TypeOrdering.h"
|
2008-04-10 10:22:51 +08:00
|
|
|
|
#include "clang/AST/StmtVisitor.h"
|
2009-08-27 07:45:07 +08:00
|
|
|
|
#include "clang/Basic/PartialDiagnostic.h"
|
2008-10-07 02:37:09 +08:00
|
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2008-08-11 11:27:53 +08:00
|
|
|
|
#include "clang/Parse/DeclSpec.h"
|
2008-12-23 08:26:44 +08:00
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2008-04-10 10:22:51 +08:00
|
|
|
|
#include "llvm/Support/Compiler.h"
|
2008-10-22 00:13:35 +08:00
|
|
|
|
#include <algorithm> // for std::equal
|
2008-10-23 01:49:05 +08:00
|
|
|
|
#include <map>
|
2008-04-08 13:04:30 +08:00
|
|
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
|
2008-04-10 10:22:51 +08:00
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
// CheckDefaultArgumentVisitor
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
2008-04-13 07:52:44 +08:00
|
|
|
|
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.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
class VISIBILITY_HIDDEN CheckDefaultArgumentVisitor
|
2008-07-27 06:17:49 +08:00
|
|
|
|
: public StmtVisitor<CheckDefaultArgumentVisitor, bool> {
|
2008-04-13 07:52:44 +08:00
|
|
|
|
Expr *DefaultArg;
|
|
|
|
|
Sema *S;
|
|
|
|
|
|
|
|
|
|
public:
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CheckDefaultArgumentVisitor(Expr *defarg, Sema *s)
|
2008-04-13 07:52:44 +08:00
|
|
|
|
: DefaultArg(defarg), S(s) {}
|
|
|
|
|
|
|
|
|
|
bool VisitExpr(Expr *Node);
|
|
|
|
|
bool VisitDeclRefExpr(DeclRefExpr *DRE);
|
2008-11-04 22:32:21 +08:00
|
|
|
|
bool VisitCXXThisExpr(CXXThisExpr *ThisE);
|
2008-04-13 07:52:44 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// VisitExpr - Visit all of the children of this expression.
|
|
|
|
|
bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) {
|
|
|
|
|
bool IsInvalid = false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
for (Stmt::child_iterator I = Node->child_begin(),
|
2008-07-27 06:17:49 +08:00
|
|
|
|
E = Node->child_end(); I != E; ++I)
|
|
|
|
|
IsInvalid |= Visit(*I);
|
2008-04-13 07:52:44 +08:00
|
|
|
|
return IsInvalid;
|
2008-04-10 10:22:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-04-13 07:52:44 +08:00
|
|
|
|
/// 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) {
|
2008-10-22 00:13:35 +08:00
|
|
|
|
NamedDecl *Decl = DRE->getDecl();
|
2008-04-13 07:52:44 +08:00
|
|
|
|
if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(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.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
return S->Diag(DRE->getSourceRange().getBegin(),
|
2008-11-19 13:08:23 +08:00
|
|
|
|
diag::err_param_default_argument_references_param)
|
2008-11-24 05:45:46 +08:00
|
|
|
|
<< Param->getDeclName() << DefaultArg->getSourceRange();
|
2008-04-16 06:42:06 +08:00
|
|
|
|
} else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) {
|
2008-04-13 07:52:44 +08:00
|
|
|
|
// C++ [dcl.fct.default]p7
|
|
|
|
|
// Local variables shall not be used in default argument
|
|
|
|
|
// expressions.
|
2008-04-16 06:42:06 +08:00
|
|
|
|
if (VDecl->isBlockVarDecl())
|
2009-09-09 23:08:12 +08:00
|
|
|
|
return S->Diag(DRE->getSourceRange().getBegin(),
|
2008-11-19 13:08:23 +08:00
|
|
|
|
diag::err_param_default_argument_references_local)
|
2008-11-24 05:45:46 +08:00
|
|
|
|
<< VDecl->getDeclName() << DefaultArg->getSourceRange();
|
2008-04-13 07:52:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-04 21:41:56 +08:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2008-04-13 07:52:44 +08:00
|
|
|
|
|
2008-11-04 22:32:21 +08:00
|
|
|
|
/// VisitCXXThisExpr - Visit a C++ "this" expression.
|
|
|
|
|
bool CheckDefaultArgumentVisitor::VisitCXXThisExpr(CXXThisExpr *ThisE) {
|
|
|
|
|
// C++ [dcl.fct.default]p8:
|
|
|
|
|
// The keyword this shall not be used in a default argument of a
|
|
|
|
|
// member function.
|
|
|
|
|
return S->Diag(ThisE->getSourceRange().getBegin(),
|
2008-11-19 13:08:23 +08:00
|
|
|
|
diag::err_param_default_argument_references_this)
|
|
|
|
|
<< ThisE->getSourceRange();
|
2008-04-13 07:52:44 +08:00
|
|
|
|
}
|
2008-04-10 10:22:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-25 10:29:20 +08:00
|
|
|
|
bool
|
|
|
|
|
Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg,
|
2009-09-09 23:08:12 +08:00
|
|
|
|
SourceLocation EqualLoc) {
|
2009-08-25 10:29:20 +08:00
|
|
|
|
QualType ParamType = Param->getType();
|
|
|
|
|
|
2009-08-25 21:46:13 +08:00
|
|
|
|
if (RequireCompleteType(Param->getLocation(), Param->getType(),
|
|
|
|
|
diag::err_typecheck_decl_incomplete_type)) {
|
|
|
|
|
Param->setInvalidDecl();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-25 10:29:20 +08:00
|
|
|
|
Expr *Arg = (Expr *)DefaultArg.get();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-25 10:29:20 +08:00
|
|
|
|
// 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).
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CheckInitializerTypes(Arg, ParamType, EqualLoc,
|
2009-08-25 10:29:20 +08:00
|
|
|
|
Param->getDeclName(), /*DirectInit=*/false))
|
2009-08-25 11:18:48 +08:00
|
|
|
|
return true;
|
2009-08-25 10:29:20 +08:00
|
|
|
|
|
|
|
|
|
Arg = MaybeCreateCXXExprWithTemporaries(Arg, /*DestroyTemps=*/false);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-25 10:29:20 +08:00
|
|
|
|
// Okay: add the default argument to the parameter
|
|
|
|
|
Param->setDefaultArg(Arg);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-25 10:29:20 +08:00
|
|
|
|
DefaultArg.release();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-25 11:18:48 +08:00
|
|
|
|
return false;
|
2009-08-25 10:29:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-04-10 10:22:51 +08:00
|
|
|
|
/// ActOnParamDefaultArgument - Check whether the default argument
|
|
|
|
|
/// provided for a function parameter is well-formed. If so, attach it
|
|
|
|
|
/// to the parameter declaration.
|
2008-04-08 13:04:30 +08:00
|
|
|
|
void
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
|
2009-03-16 01:47:39 +08:00
|
|
|
|
ExprArg defarg) {
|
2009-06-23 07:20:33 +08:00
|
|
|
|
if (!param || !defarg.get())
|
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-29 03:18:32 +08:00
|
|
|
|
ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
|
2009-06-13 00:51:40 +08:00
|
|
|
|
UnparsedDefaultArgLocs.erase(Param);
|
|
|
|
|
|
2009-05-02 03:30:39 +08:00
|
|
|
|
ExprOwningPtr<Expr> DefaultArg(this, defarg.takeAs<Expr>());
|
2008-04-08 13:04:30 +08:00
|
|
|
|
QualType ParamType = Param->getType();
|
|
|
|
|
|
|
|
|
|
// Default arguments are only permitted in C++
|
|
|
|
|
if (!getLangOptions().CPlusPlus) {
|
2008-11-19 13:08:23 +08:00
|
|
|
|
Diag(EqualLoc, diag::err_param_default_argument)
|
|
|
|
|
<< DefaultArg->getSourceRange();
|
2008-12-17 05:30:33 +08:00
|
|
|
|
Param->setInvalidDecl();
|
2008-04-08 13:04:30 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-25 09:02:06 +08:00
|
|
|
|
// Check that the default argument is well-formed
|
|
|
|
|
CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg.get(), this);
|
|
|
|
|
if (DefaultArgChecker.Visit(DefaultArg.get())) {
|
|
|
|
|
Param->setInvalidDecl();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-25 10:29:20 +08:00
|
|
|
|
SetParamDefaultArgument(Param, move(DefaultArg), EqualLoc);
|
2008-04-08 13:04:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-12-24 08:01:03 +08:00
|
|
|
|
/// 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.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
|
2009-06-13 00:51:40 +08:00
|
|
|
|
SourceLocation EqualLoc,
|
|
|
|
|
SourceLocation ArgLoc) {
|
2009-06-23 07:20:33 +08:00
|
|
|
|
if (!param)
|
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-29 03:18:32 +08:00
|
|
|
|
ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
|
2008-12-24 08:01:03 +08:00
|
|
|
|
if (Param)
|
|
|
|
|
Param->setUnparsedDefaultArg();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-13 00:51:40 +08:00
|
|
|
|
UnparsedDefaultArgLocs[Param] = ArgLoc;
|
2008-12-24 08:01:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-12-17 05:30:33 +08:00
|
|
|
|
/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
|
|
|
|
|
/// the default argument for the parameter param failed.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
void Sema::ActOnParamDefaultArgumentError(DeclPtrTy param) {
|
2009-06-23 07:20:33 +08:00
|
|
|
|
if (!param)
|
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-13 00:51:40 +08:00
|
|
|
|
ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-13 00:51:40 +08:00
|
|
|
|
Param->setInvalidDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-13 00:51:40 +08:00
|
|
|
|
UnparsedDefaultArgLocs.erase(Param);
|
2008-12-17 05:30:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-05-07 12:49:29 +08:00
|
|
|
|
/// CheckExtraCXXDefaultArguments - Check for any extra default
|
|
|
|
|
/// arguments in the declarator, which is not a function declaration
|
|
|
|
|
/// or definition and therefore is not permitted to have default
|
|
|
|
|
/// arguments. This routine should be invoked for every declarator
|
|
|
|
|
/// that is not a function declaration or definition.
|
|
|
|
|
void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
|
|
|
|
|
// 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.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
|
2008-05-07 12:49:29 +08:00
|
|
|
|
DeclaratorChunk &chunk = D.getTypeObject(i);
|
|
|
|
|
if (chunk.Kind == DeclaratorChunk::Function) {
|
2009-03-29 03:18:32 +08:00
|
|
|
|
for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) {
|
|
|
|
|
ParmVarDecl *Param =
|
|
|
|
|
cast<ParmVarDecl>(chunk.Fun.ArgInfo[argIdx].Param.getAs<Decl>());
|
2008-12-24 08:01:03 +08:00
|
|
|
|
if (Param->hasUnparsedDefaultArg()) {
|
|
|
|
|
CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens;
|
2008-12-17 05:30:33 +08:00
|
|
|
|
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
|
|
|
|
|
<< SourceRange((*Toks)[1].getLocation(), Toks->back().getLocation());
|
|
|
|
|
delete Toks;
|
|
|
|
|
chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0;
|
2008-12-24 08:01:03 +08:00
|
|
|
|
} else if (Param->getDefaultArg()) {
|
|
|
|
|
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
|
|
|
|
|
<< Param->getDefaultArg()->getSourceRange();
|
|
|
|
|
Param->setDefaultArg(0);
|
2008-05-07 12:49:29 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-04-08 13:04:30 +08:00
|
|
|
|
// MergeCXXFunctionDecl - Merge two declarations of the same C++
|
|
|
|
|
// function, once we already know that they have the same
|
2009-02-17 01:45:42 +08:00
|
|
|
|
// type. Subroutine of MergeFunctionDecl. Returns true if there was an
|
|
|
|
|
// error, false otherwise.
|
|
|
|
|
bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
|
|
|
|
|
bool Invalid = false;
|
|
|
|
|
|
2008-04-08 13:04:30 +08:00
|
|
|
|
// 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).
|
2009-09-12 02:44:32 +08:00
|
|
|
|
//
|
|
|
|
|
// C++ [dcl.fct.default]p6:
|
|
|
|
|
// Except for member functions of class templates, the default arguments
|
|
|
|
|
// in a member function definition that appears outside of the class
|
|
|
|
|
// definition are added to the set of default arguments provided by the
|
|
|
|
|
// member function declaration in the class definition.
|
2008-04-08 13:04:30 +08:00
|
|
|
|
for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) {
|
|
|
|
|
ParmVarDecl *OldParam = Old->getParamDecl(p);
|
|
|
|
|
ParmVarDecl *NewParam = New->getParamDecl(p);
|
|
|
|
|
|
2009-09-12 02:44:32 +08:00
|
|
|
|
if (OldParam->hasDefaultArg() && NewParam->hasDefaultArg()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(NewParam->getLocation(),
|
2008-11-19 13:08:23 +08:00
|
|
|
|
diag::err_param_default_argument_redefinition)
|
2009-09-12 02:44:32 +08:00
|
|
|
|
<< NewParam->getDefaultArgRange();
|
|
|
|
|
|
|
|
|
|
// Look for the function declaration where the default argument was
|
|
|
|
|
// actually written, which may be a declaration prior to Old.
|
|
|
|
|
for (FunctionDecl *Older = Old->getPreviousDeclaration();
|
|
|
|
|
Older; Older = Older->getPreviousDeclaration()) {
|
|
|
|
|
if (!Older->getParamDecl(p)->hasDefaultArg())
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
OldParam = Older->getParamDecl(p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Diag(OldParam->getLocation(), diag::note_previous_definition)
|
|
|
|
|
<< OldParam->getDefaultArgRange();
|
2009-02-17 01:45:42 +08:00
|
|
|
|
Invalid = true;
|
2008-04-08 13:04:30 +08:00
|
|
|
|
} else if (OldParam->getDefaultArg()) {
|
|
|
|
|
// Merge the old default argument into the new parameter
|
|
|
|
|
NewParam->setDefaultArg(OldParam->getDefaultArg());
|
2009-09-12 02:44:32 +08:00
|
|
|
|
} else if (NewParam->hasDefaultArg()) {
|
|
|
|
|
if (New->getDescribedFunctionTemplate()) {
|
|
|
|
|
// Paragraph 4, quoted above, only applies to non-template functions.
|
|
|
|
|
Diag(NewParam->getLocation(),
|
|
|
|
|
diag::err_param_default_argument_template_redecl)
|
|
|
|
|
<< NewParam->getDefaultArgRange();
|
|
|
|
|
Diag(Old->getLocation(), diag::note_template_prev_declaration)
|
|
|
|
|
<< false;
|
|
|
|
|
} else if (New->getDeclContext()->isDependentContext()) {
|
|
|
|
|
// C++ [dcl.fct.default]p6 (DR217):
|
|
|
|
|
// Default arguments for a member function of a class template shall
|
|
|
|
|
// be specified on the initial declaration of the member function
|
|
|
|
|
// within the class template.
|
|
|
|
|
//
|
|
|
|
|
// Reading the tea leaves a bit in DR217 and its reference to DR205
|
|
|
|
|
// leads me to the conclusion that one cannot add default function
|
|
|
|
|
// arguments for an out-of-line definition of a member function of a
|
|
|
|
|
// dependent type.
|
|
|
|
|
int WhichKind = 2;
|
|
|
|
|
if (CXXRecordDecl *Record
|
|
|
|
|
= dyn_cast<CXXRecordDecl>(New->getDeclContext())) {
|
|
|
|
|
if (Record->getDescribedClassTemplate())
|
|
|
|
|
WhichKind = 0;
|
|
|
|
|
else if (isa<ClassTemplatePartialSpecializationDecl>(Record))
|
|
|
|
|
WhichKind = 1;
|
|
|
|
|
else
|
|
|
|
|
WhichKind = 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Diag(NewParam->getLocation(),
|
|
|
|
|
diag::err_param_default_argument_member_template_redecl)
|
|
|
|
|
<< WhichKind
|
|
|
|
|
<< NewParam->getDefaultArgRange();
|
|
|
|
|
}
|
2008-04-08 13:04:30 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-04 19:39:00 +08:00
|
|
|
|
if (CheckEquivalentExceptionSpec(
|
|
|
|
|
Old->getType()->getAsFunctionProtoType(), Old->getLocation(),
|
|
|
|
|
New->getType()->getAsFunctionProtoType(), New->getLocation())) {
|
|
|
|
|
Invalid = true;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-17 01:45:42 +08:00
|
|
|
|
return Invalid;
|
2008-04-08 13:04:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 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);
|
2009-08-25 09:23:32 +08:00
|
|
|
|
if (Param->hasDefaultArg())
|
2008-04-08 13:04:30 +08:00
|
|
|
|
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;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
for (; p < NumParams; ++p) {
|
2008-04-08 13:04:30 +08:00
|
|
|
|
ParmVarDecl *Param = FD->getParamDecl(p);
|
2009-08-25 09:23:32 +08:00
|
|
|
|
if (!Param->hasDefaultArg()) {
|
2008-12-17 05:30:33 +08:00
|
|
|
|
if (Param->isInvalidDecl())
|
|
|
|
|
/* We already complained about this parameter. */;
|
|
|
|
|
else if (Param->getIdentifier())
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(Param->getLocation(),
|
2008-11-19 13:08:23 +08:00
|
|
|
|
diag::err_param_default_argument_missing_name)
|
2008-11-19 15:32:16 +08:00
|
|
|
|
<< Param->getIdentifier();
|
2008-04-08 13:04:30 +08:00
|
|
|
|
else
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(Param->getLocation(),
|
2008-04-08 13:04:30 +08:00
|
|
|
|
diag::err_param_default_argument_missing);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2008-04-08 13:04:30 +08:00
|
|
|
|
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);
|
2009-06-13 00:51:40 +08:00
|
|
|
|
if (Param->hasDefaultArg()) {
|
2008-12-24 08:01:03 +08:00
|
|
|
|
if (!Param->hasUnparsedDefaultArg())
|
|
|
|
|
Param->getDefaultArg()->Destroy(Context);
|
2008-04-08 13:04:30 +08:00
|
|
|
|
Param->setDefaultArg(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-04-14 05:30:24 +08:00
|
|
|
|
|
2008-10-31 17:07:45 +08:00
|
|
|
|
/// isCurrentClassName - Determine whether the identifier II is the
|
|
|
|
|
/// name of the class type currently being defined. In the case of
|
|
|
|
|
/// nested classes, this will only return true if II is the name of
|
|
|
|
|
/// the innermost class.
|
2008-11-09 00:45:02 +08:00
|
|
|
|
bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *,
|
|
|
|
|
const CXXScopeSpec *SS) {
|
2008-11-09 01:17:31 +08:00
|
|
|
|
CXXRecordDecl *CurDecl;
|
Introduce a representation for types that we referred to via a
qualified name, e.g.,
foo::x
so that we retain the nested-name-specifier as written in the source
code and can reproduce that qualified name when printing the types
back (e.g., in diagnostics). This is PR3493, which won't be complete
until finished the other tasks mentioned near the end of this commit.
The parser's representation of nested-name-specifiers, CXXScopeSpec,
is now a bit fatter, because it needs to contain the scopes that
precede each '::' and keep track of whether the global scoping
operator '::' was at the beginning. For example, we need to keep track
of the leading '::', 'foo', and 'bar' in
::foo::bar::x
The Action's CXXScopeTy * is no longer a DeclContext *. It's now the
opaque version of the new NestedNameSpecifier, which contains a single
component of a nested-name-specifier (either a DeclContext * or a Type
*, bitmangled).
The new sugar type QualifiedNameType composes a sequence of
NestedNameSpecifiers with a representation of the type we're actually
referring to. At present, we only build QualifiedNameType nodes within
Sema::getTypeName. This will be extended to other type-constructing
actions (e.g., ActOnClassTemplateId).
Also on the way: QualifiedDeclRefExprs will also store a sequence of
NestedNameSpecifiers, so that we can print out the property
nested-name-specifier. I expect to also use this for handling
dependent names like Fibonacci<I - 1>::value.
llvm-svn: 67265
2009-03-19 08:18:19 +08:00
|
|
|
|
if (SS && SS->isSet() && !SS->isInvalid()) {
|
2009-08-22 06:16:40 +08:00
|
|
|
|
DeclContext *DC = computeDeclContext(*SS, true);
|
2008-11-09 01:17:31 +08:00
|
|
|
|
CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC);
|
|
|
|
|
} else
|
|
|
|
|
CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
|
|
|
|
|
|
|
|
|
|
if (CurDecl)
|
2008-10-31 17:07:45 +08:00
|
|
|
|
return &II == CurDecl->getIdentifier();
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
/// \brief Check the validity of a C++ base class specifier.
|
2009-03-03 12:44:36 +08:00
|
|
|
|
///
|
|
|
|
|
/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics
|
|
|
|
|
/// and returns NULL otherwise.
|
|
|
|
|
CXXBaseSpecifier *
|
|
|
|
|
Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
|
|
|
|
|
SourceRange SpecifierRange,
|
2008-10-23 01:49:05 +08:00
|
|
|
|
bool Virtual, AccessSpecifier Access,
|
2009-09-09 23:08:12 +08:00
|
|
|
|
QualType BaseType,
|
2009-03-03 12:44:36 +08:00
|
|
|
|
SourceLocation BaseLoc) {
|
|
|
|
|
// C++ [class.union]p1:
|
|
|
|
|
// A union shall not have base classes.
|
|
|
|
|
if (Class->isUnion()) {
|
|
|
|
|
Diag(Class->getLocation(), diag::err_base_clause_on_union)
|
|
|
|
|
<< SpecifierRange;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (BaseType->isDependentType())
|
2009-09-09 23:08:12 +08:00
|
|
|
|
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
|
2009-03-03 12:44:36 +08:00
|
|
|
|
Class->getTagKind() == RecordDecl::TK_class,
|
|
|
|
|
Access, BaseType);
|
2008-04-14 05:30:24 +08:00
|
|
|
|
|
|
|
|
|
// Base specifiers must be record types.
|
2009-03-03 12:44:36 +08:00
|
|
|
|
if (!BaseType->isRecordType()) {
|
|
|
|
|
Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2008-04-14 05:30:24 +08:00
|
|
|
|
|
|
|
|
|
// C++ [class.union]p1:
|
|
|
|
|
// A union shall not be used as a base class.
|
2009-03-03 12:44:36 +08:00
|
|
|
|
if (BaseType->isUnionType()) {
|
|
|
|
|
Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2008-04-14 05:30:24 +08:00
|
|
|
|
|
|
|
|
|
// C++ [class.derived]p2:
|
|
|
|
|
// The class-name in a base-specifier shall not be an incompletely
|
|
|
|
|
// defined class.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (RequireCompleteType(BaseLoc, BaseType,
|
2009-08-27 07:45:07 +08:00
|
|
|
|
PDiag(diag::err_incomplete_base_class)
|
|
|
|
|
<< SpecifierRange))
|
2009-03-03 12:44:36 +08:00
|
|
|
|
return 0;
|
2008-04-14 05:30:24 +08:00
|
|
|
|
|
2009-08-16 05:55:26 +08:00
|
|
|
|
// If the base class is polymorphic or isn't empty, the new one is/isn't, too.
|
2009-07-30 05:53:49 +08:00
|
|
|
|
RecordDecl *BaseDecl = BaseType->getAs<RecordType>()->getDecl();
|
2008-11-06 23:59:35 +08:00
|
|
|
|
assert(BaseDecl && "Record type has no declaration");
|
|
|
|
|
BaseDecl = BaseDecl->getDefinition(Context);
|
|
|
|
|
assert(BaseDecl && "Base type is not incomplete, but has no definition");
|
2009-08-16 05:55:26 +08:00
|
|
|
|
CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
|
|
|
|
|
assert(CXXBaseDecl && "Base type is not a C++ type");
|
|
|
|
|
if (!CXXBaseDecl->isEmpty())
|
|
|
|
|
Class->setEmpty(false);
|
|
|
|
|
if (CXXBaseDecl->isPolymorphic())
|
2009-03-03 12:44:36 +08:00
|
|
|
|
Class->setPolymorphic(true);
|
2009-01-06 04:52:13 +08:00
|
|
|
|
|
|
|
|
|
// C++ [dcl.init.aggr]p1:
|
|
|
|
|
// An aggregate is [...] a class with [...] no base classes [...].
|
2009-03-03 12:44:36 +08:00
|
|
|
|
Class->setAggregate(false);
|
|
|
|
|
Class->setPOD(false);
|
2008-11-06 23:59:35 +08:00
|
|
|
|
|
2009-04-16 08:08:20 +08:00
|
|
|
|
if (Virtual) {
|
|
|
|
|
// C++ [class.ctor]p5:
|
|
|
|
|
// A constructor is trivial if its class has no virtual base classes.
|
|
|
|
|
Class->setHasTrivialConstructor(false);
|
2009-07-23 02:25:24 +08:00
|
|
|
|
|
|
|
|
|
// C++ [class.copy]p6:
|
|
|
|
|
// A copy constructor is trivial if its class has no virtual base classes.
|
|
|
|
|
Class->setHasTrivialCopyConstructor(false);
|
|
|
|
|
|
|
|
|
|
// C++ [class.copy]p11:
|
|
|
|
|
// A copy assignment operator is trivial if its class has no virtual
|
|
|
|
|
// base classes.
|
|
|
|
|
Class->setHasTrivialCopyAssignment(false);
|
2009-08-16 05:55:26 +08:00
|
|
|
|
|
|
|
|
|
// C++0x [meta.unary.prop] is_empty:
|
|
|
|
|
// T is a class type, but not a union type, with ... no virtual base
|
|
|
|
|
// classes
|
|
|
|
|
Class->setEmpty(false);
|
2009-04-16 08:08:20 +08:00
|
|
|
|
} else {
|
|
|
|
|
// C++ [class.ctor]p5:
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// A constructor is trivial if all the direct base classes of its
|
2009-04-16 08:08:20 +08:00
|
|
|
|
// class have trivial constructors.
|
2009-07-23 02:25:24 +08:00
|
|
|
|
if (!cast<CXXRecordDecl>(BaseDecl)->hasTrivialConstructor())
|
|
|
|
|
Class->setHasTrivialConstructor(false);
|
|
|
|
|
|
|
|
|
|
// C++ [class.copy]p6:
|
|
|
|
|
// A copy constructor is trivial if all the direct base classes of its
|
|
|
|
|
// class have trivial copy constructors.
|
|
|
|
|
if (!cast<CXXRecordDecl>(BaseDecl)->hasTrivialCopyConstructor())
|
|
|
|
|
Class->setHasTrivialCopyConstructor(false);
|
|
|
|
|
|
|
|
|
|
// C++ [class.copy]p11:
|
|
|
|
|
// A copy assignment operator is trivial if all the direct base classes
|
|
|
|
|
// of its class have trivial copy assignment operators.
|
|
|
|
|
if (!cast<CXXRecordDecl>(BaseDecl)->hasTrivialCopyAssignment())
|
|
|
|
|
Class->setHasTrivialCopyAssignment(false);
|
2009-04-16 08:08:20 +08:00
|
|
|
|
}
|
2009-04-17 10:34:54 +08:00
|
|
|
|
|
|
|
|
|
// C++ [class.ctor]p3:
|
|
|
|
|
// A destructor is trivial if all the direct base classes of its class
|
|
|
|
|
// have trivial destructors.
|
2009-07-23 02:25:24 +08:00
|
|
|
|
if (!cast<CXXRecordDecl>(BaseDecl)->hasTrivialDestructor())
|
|
|
|
|
Class->setHasTrivialDestructor(false);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2008-10-23 01:49:05 +08:00
|
|
|
|
// Create the base specifier.
|
2009-03-03 12:44:36 +08:00
|
|
|
|
// FIXME: Allocate via ASTContext?
|
2009-09-09 23:08:12 +08:00
|
|
|
|
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
|
|
|
|
|
Class->getTagKind() == RecordDecl::TK_class,
|
2009-03-03 12:44:36 +08:00
|
|
|
|
Access, BaseType);
|
2008-10-23 01:49:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-03-03 12:44:36 +08:00
|
|
|
|
/// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is
|
|
|
|
|
/// one entry in the base class list of a class specifier, for
|
2009-09-09 23:08:12 +08:00
|
|
|
|
/// example:
|
|
|
|
|
/// class foo : public bar, virtual private baz {
|
2009-03-03 12:44:36 +08:00
|
|
|
|
/// 'public bar' and 'virtual private baz' are each base-specifiers.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Sema::BaseResult
|
2009-03-29 03:18:32 +08:00
|
|
|
|
Sema::ActOnBaseSpecifier(DeclPtrTy classdecl, SourceRange SpecifierRange,
|
2009-03-03 12:44:36 +08:00
|
|
|
|
bool Virtual, AccessSpecifier Access,
|
|
|
|
|
TypeTy *basetype, SourceLocation BaseLoc) {
|
2009-06-23 07:20:33 +08:00
|
|
|
|
if (!classdecl)
|
|
|
|
|
return true;
|
|
|
|
|
|
2009-03-10 07:48:35 +08:00
|
|
|
|
AdjustDeclIfTemplate(classdecl);
|
2009-03-29 03:18:32 +08:00
|
|
|
|
CXXRecordDecl *Class = cast<CXXRecordDecl>(classdecl.getAs<Decl>());
|
2009-08-19 09:28:28 +08:00
|
|
|
|
QualType BaseType = GetTypeFromParser(basetype);
|
2009-03-03 12:44:36 +08:00
|
|
|
|
if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange,
|
|
|
|
|
Virtual, Access,
|
|
|
|
|
BaseType, BaseLoc))
|
|
|
|
|
return BaseSpec;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-03 12:44:36 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// \brief Performs the actual work of attaching the given base class
|
|
|
|
|
/// specifiers to a C++ class.
|
|
|
|
|
bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
|
|
|
|
|
unsigned NumBases) {
|
|
|
|
|
if (NumBases == 0)
|
|
|
|
|
return false;
|
2008-10-23 01:49:05 +08:00
|
|
|
|
|
|
|
|
|
// Used to keep track of which base types we have already seen, so
|
|
|
|
|
// that we can properly diagnose redundant direct base types. Note
|
2008-10-24 02:13:27 +08:00
|
|
|
|
// that the key is always the unqualified canonical type of the base
|
|
|
|
|
// class.
|
2008-10-23 01:49:05 +08:00
|
|
|
|
std::map<QualType, CXXBaseSpecifier*, QualTypeOrdering> KnownBaseTypes;
|
|
|
|
|
|
|
|
|
|
// Copy non-redundant base specifiers into permanent storage.
|
2008-10-24 02:13:27 +08:00
|
|
|
|
unsigned NumGoodBases = 0;
|
2009-03-03 12:44:36 +08:00
|
|
|
|
bool Invalid = false;
|
2008-10-24 02:13:27 +08:00
|
|
|
|
for (unsigned idx = 0; idx < NumBases; ++idx) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
QualType NewBaseType
|
2009-03-03 12:44:36 +08:00
|
|
|
|
= Context.getCanonicalType(Bases[idx]->getType());
|
2008-10-24 02:13:27 +08:00
|
|
|
|
NewBaseType = NewBaseType.getUnqualifiedType();
|
|
|
|
|
|
2008-10-23 01:49:05 +08:00
|
|
|
|
if (KnownBaseTypes[NewBaseType]) {
|
|
|
|
|
// C++ [class.mi]p3:
|
|
|
|
|
// A class shall not be specified as a direct base class of a
|
|
|
|
|
// derived class more than once.
|
2009-03-03 12:44:36 +08:00
|
|
|
|
Diag(Bases[idx]->getSourceRange().getBegin(),
|
2008-11-19 13:08:23 +08:00
|
|
|
|
diag::err_duplicate_base_class)
|
2008-11-24 14:25:27 +08:00
|
|
|
|
<< KnownBaseTypes[NewBaseType]->getType()
|
2009-03-03 12:44:36 +08:00
|
|
|
|
<< Bases[idx]->getSourceRange();
|
2008-10-24 02:13:27 +08:00
|
|
|
|
|
|
|
|
|
// Delete the duplicate base class specifier; we're going to
|
|
|
|
|
// overwrite its pointer later.
|
2009-07-23 04:55:49 +08:00
|
|
|
|
Context.Deallocate(Bases[idx]);
|
2009-03-03 12:44:36 +08:00
|
|
|
|
|
|
|
|
|
Invalid = true;
|
2008-10-23 01:49:05 +08:00
|
|
|
|
} else {
|
|
|
|
|
// Okay, add this new base class.
|
2009-03-03 12:44:36 +08:00
|
|
|
|
KnownBaseTypes[NewBaseType] = Bases[idx];
|
|
|
|
|
Bases[NumGoodBases++] = Bases[idx];
|
2008-10-23 01:49:05 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2008-04-14 05:30:24 +08:00
|
|
|
|
|
2008-10-23 01:49:05 +08:00
|
|
|
|
// Attach the remaining base class specifiers to the derived class.
|
2009-07-03 02:26:15 +08:00
|
|
|
|
Class->setBases(Context, Bases, NumGoodBases);
|
2008-10-24 02:13:27 +08:00
|
|
|
|
|
|
|
|
|
// Delete the remaining (good) base class specifiers, since their
|
|
|
|
|
// data has been copied into the CXXRecordDecl.
|
|
|
|
|
for (unsigned idx = 0; idx < NumGoodBases; ++idx)
|
2009-07-23 04:55:49 +08:00
|
|
|
|
Context.Deallocate(Bases[idx]);
|
2009-03-03 12:44:36 +08:00
|
|
|
|
|
|
|
|
|
return Invalid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// ActOnBaseSpecifiers - Attach the given base specifiers to the
|
|
|
|
|
/// class, after checking whether there are any duplicate base
|
|
|
|
|
/// classes.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
void Sema::ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases,
|
2009-03-03 12:44:36 +08:00
|
|
|
|
unsigned NumBases) {
|
|
|
|
|
if (!ClassDecl || !Bases || !NumBases)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
AdjustDeclIfTemplate(ClassDecl);
|
2009-03-29 03:18:32 +08:00
|
|
|
|
AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl.getAs<Decl>()),
|
2009-03-03 12:44:36 +08:00
|
|
|
|
(CXXBaseSpecifier**)(Bases), NumBases);
|
2008-04-14 05:30:24 +08:00
|
|
|
|
}
|
2008-04-27 21:50:30 +08:00
|
|
|
|
|
2008-07-01 18:37:29 +08:00
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
// C++ class member Handling
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
/// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
|
|
|
|
|
/// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the
|
|
|
|
|
/// bitfield width if there is one and 'InitExpr' specifies the initializer if
|
2009-04-13 06:37:57 +08:00
|
|
|
|
/// any.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
Sema::DeclPtrTy
|
2008-07-01 18:37:29 +08:00
|
|
|
|
Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
|
2009-08-21 06:52:58 +08:00
|
|
|
|
MultiTemplateParamsArg TemplateParameterLists,
|
2009-04-13 01:16:29 +08:00
|
|
|
|
ExprTy *BW, ExprTy *InitExpr, bool Deleted) {
|
2008-07-01 18:37:29 +08:00
|
|
|
|
const DeclSpec &DS = D.getDeclSpec();
|
2008-11-18 06:58:34 +08:00
|
|
|
|
DeclarationName Name = GetNameForDeclarator(D);
|
2008-07-01 18:37:29 +08:00
|
|
|
|
Expr *BitWidth = static_cast<Expr*>(BW);
|
|
|
|
|
Expr *Init = static_cast<Expr*>(InitExpr);
|
|
|
|
|
SourceLocation Loc = D.getIdentifierLoc();
|
|
|
|
|
|
2008-11-15 07:42:31 +08:00
|
|
|
|
bool isFunc = D.isFunctionDeclarator();
|
|
|
|
|
|
2009-08-06 10:15:43 +08:00
|
|
|
|
assert(!DS.isFriendSpecified());
|
|
|
|
|
|
2008-07-01 18:37:29 +08:00
|
|
|
|
// C++ 9.2p6: A member shall not be declared to have automatic storage
|
|
|
|
|
// duration (auto, register) or with the extern storage-class-specifier.
|
2008-11-15 07:42:31 +08:00
|
|
|
|
// C++ 7.1.1p8: The mutable specifier can be applied only to names of class
|
|
|
|
|
// data members and cannot be applied to names declared const or static,
|
|
|
|
|
// and cannot be applied to reference members.
|
2008-07-01 18:37:29 +08:00
|
|
|
|
switch (DS.getStorageClassSpec()) {
|
|
|
|
|
case DeclSpec::SCS_unspecified:
|
|
|
|
|
case DeclSpec::SCS_typedef:
|
|
|
|
|
case DeclSpec::SCS_static:
|
|
|
|
|
// FALL THROUGH.
|
|
|
|
|
break;
|
2008-11-15 07:42:31 +08:00
|
|
|
|
case DeclSpec::SCS_mutable:
|
|
|
|
|
if (isFunc) {
|
|
|
|
|
if (DS.getStorageClassSpecLoc().isValid())
|
2008-11-19 13:08:23 +08:00
|
|
|
|
Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_function);
|
2008-11-15 07:42:31 +08:00
|
|
|
|
else
|
2008-11-19 13:08:23 +08:00
|
|
|
|
Diag(DS.getThreadSpecLoc(), diag::err_mutable_function);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2008-11-18 07:24:37 +08:00
|
|
|
|
// FIXME: It would be nicer if the keyword was ignored only for this
|
|
|
|
|
// declarator. Otherwise we could get follow-up errors.
|
2008-11-15 07:42:31 +08:00
|
|
|
|
D.getMutableDeclSpec().ClearStorageClassSpecs();
|
|
|
|
|
} else {
|
|
|
|
|
QualType T = GetTypeForDeclarator(D, S);
|
|
|
|
|
diag::kind err = static_cast<diag::kind>(0);
|
|
|
|
|
if (T->isReferenceType())
|
|
|
|
|
err = diag::err_mutable_reference;
|
|
|
|
|
else if (T.isConstQualified())
|
|
|
|
|
err = diag::err_mutable_const;
|
|
|
|
|
if (err != 0) {
|
|
|
|
|
if (DS.getStorageClassSpecLoc().isValid())
|
|
|
|
|
Diag(DS.getStorageClassSpecLoc(), err);
|
|
|
|
|
else
|
|
|
|
|
Diag(DS.getThreadSpecLoc(), err);
|
2008-11-18 07:24:37 +08:00
|
|
|
|
// FIXME: It would be nicer if the keyword was ignored only for this
|
|
|
|
|
// declarator. Otherwise we could get follow-up errors.
|
2008-11-15 07:42:31 +08:00
|
|
|
|
D.getMutableDeclSpec().ClearStorageClassSpecs();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2008-07-01 18:37:29 +08:00
|
|
|
|
default:
|
|
|
|
|
if (DS.getStorageClassSpecLoc().isValid())
|
|
|
|
|
Diag(DS.getStorageClassSpecLoc(),
|
|
|
|
|
diag::err_storageclass_invalid_for_member);
|
|
|
|
|
else
|
|
|
|
|
Diag(DS.getThreadSpecLoc(), diag::err_storageclass_invalid_for_member);
|
|
|
|
|
D.getMutableDeclSpec().ClearStorageClassSpecs();
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-16 04:23:22 +08:00
|
|
|
|
if (!isFunc &&
|
2009-02-09 23:09:02 +08:00
|
|
|
|
D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_typename &&
|
2008-10-16 04:23:22 +08:00
|
|
|
|
D.getNumTypeObjects() == 0) {
|
2008-10-09 06:20:31 +08:00
|
|
|
|
// Check also for this case:
|
|
|
|
|
//
|
|
|
|
|
// typedef int f();
|
|
|
|
|
// f a;
|
|
|
|
|
//
|
2009-08-19 09:28:28 +08:00
|
|
|
|
QualType TDType = GetTypeFromParser(DS.getTypeRep());
|
2009-02-09 23:09:02 +08:00
|
|
|
|
isFunc = TDType->isFunctionType();
|
2008-10-09 06:20:31 +08:00
|
|
|
|
}
|
2008-07-01 18:37:29 +08:00
|
|
|
|
|
2008-11-15 07:42:31 +08:00
|
|
|
|
bool isInstField = ((DS.getStorageClassSpec() == DeclSpec::SCS_unspecified ||
|
|
|
|
|
DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
|
2008-10-09 06:20:31 +08:00
|
|
|
|
!isFunc);
|
2008-07-01 18:37:29 +08:00
|
|
|
|
|
|
|
|
|
Decl *Member;
|
2009-03-06 06:45:59 +08:00
|
|
|
|
if (isInstField) {
|
2009-08-21 06:52:58 +08:00
|
|
|
|
// FIXME: Check for template parameters!
|
2009-03-12 04:50:30 +08:00
|
|
|
|
Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
|
|
|
|
|
AS);
|
2009-03-06 07:03:49 +08:00
|
|
|
|
assert(Member && "HandleField never returns null");
|
2009-03-06 06:45:59 +08:00
|
|
|
|
} else {
|
2009-08-21 06:52:58 +08:00
|
|
|
|
Member = HandleDeclarator(S, D, move(TemplateParameterLists), false)
|
|
|
|
|
.getAs<Decl>();
|
2009-03-06 07:03:49 +08:00
|
|
|
|
if (!Member) {
|
|
|
|
|
if (BitWidth) DeleteExpr(BitWidth);
|
2009-03-30 00:50:03 +08:00
|
|
|
|
return DeclPtrTy();
|
2009-03-06 07:03:49 +08:00
|
|
|
|
}
|
2009-03-06 07:01:03 +08:00
|
|
|
|
|
|
|
|
|
// Non-instance-fields can't have a bitfield.
|
|
|
|
|
if (BitWidth) {
|
|
|
|
|
if (Member->isInvalidDecl()) {
|
|
|
|
|
// don't emit another diagnostic.
|
2009-03-12 04:22:50 +08:00
|
|
|
|
} else if (isa<VarDecl>(Member)) {
|
2009-03-06 07:01:03 +08:00
|
|
|
|
// C++ 9.6p3: A bit-field shall not be a static member.
|
|
|
|
|
// "static member 'A' cannot be a bit-field"
|
|
|
|
|
Diag(Loc, diag::err_static_not_bitfield)
|
|
|
|
|
<< Name << BitWidth->getSourceRange();
|
|
|
|
|
} else if (isa<TypedefDecl>(Member)) {
|
|
|
|
|
// "typedef member 'x' cannot be a bit-field"
|
|
|
|
|
Diag(Loc, diag::err_typedef_not_bitfield)
|
|
|
|
|
<< Name << BitWidth->getSourceRange();
|
|
|
|
|
} else {
|
|
|
|
|
// A function typedef ("typedef int f(); f a;").
|
|
|
|
|
// C++ 9.6p3: A bit-field shall have integral or enumeration type.
|
|
|
|
|
Diag(Loc, diag::err_not_integral_type_bitfield)
|
2009-09-09 23:08:12 +08:00
|
|
|
|
<< Name << cast<ValueDecl>(Member)->getType()
|
2009-03-12 02:59:21 +08:00
|
|
|
|
<< BitWidth->getSourceRange();
|
2009-03-06 07:01:03 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-06 07:01:03 +08:00
|
|
|
|
DeleteExpr(BitWidth);
|
|
|
|
|
BitWidth = 0;
|
|
|
|
|
Member->setInvalidDecl();
|
|
|
|
|
}
|
2009-03-12 04:50:30 +08:00
|
|
|
|
|
|
|
|
|
Member->setAccess(AS);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-21 06:52:58 +08:00
|
|
|
|
// If we have declared a member function template, set the access of the
|
|
|
|
|
// templated declaration as well.
|
|
|
|
|
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
|
|
|
|
|
FunTmpl->getTemplatedDecl()->setAccess(AS);
|
2009-03-06 06:45:59 +08:00
|
|
|
|
}
|
2008-07-01 18:37:29 +08:00
|
|
|
|
|
2008-11-18 06:58:34 +08:00
|
|
|
|
assert((Name || isInstField) && "No identifier for non-field ?");
|
2008-07-01 18:37:29 +08:00
|
|
|
|
|
2009-03-12 07:00:04 +08:00
|
|
|
|
if (Init)
|
2009-03-29 03:18:32 +08:00
|
|
|
|
AddInitializerToDecl(DeclPtrTy::make(Member), ExprArg(*this, Init), false);
|
2009-04-13 01:16:29 +08:00
|
|
|
|
if (Deleted) // FIXME: Source location is not very good.
|
|
|
|
|
SetDeclDeleted(DeclPtrTy::make(Member), D.getSourceRange().getBegin());
|
2008-07-01 18:37:29 +08:00
|
|
|
|
|
|
|
|
|
if (isInstField) {
|
2008-12-12 00:49:14 +08:00
|
|
|
|
FieldCollector->Add(cast<FieldDecl>(Member));
|
2009-03-30 00:50:03 +08:00
|
|
|
|
return DeclPtrTy();
|
2008-07-01 18:37:29 +08:00
|
|
|
|
}
|
2009-03-29 03:18:32 +08:00
|
|
|
|
return DeclPtrTy::make(Member);
|
2008-07-01 18:37:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-05 12:29:56 +08:00
|
|
|
|
/// ActOnMemInitializer - Handle a C++ member initializer.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Sema::MemInitResult
|
2009-03-29 03:18:32 +08:00
|
|
|
|
Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
|
2008-11-05 12:29:56 +08:00
|
|
|
|
Scope *S,
|
2009-07-01 07:26:25 +08:00
|
|
|
|
const CXXScopeSpec &SS,
|
2008-11-05 12:29:56 +08:00
|
|
|
|
IdentifierInfo *MemberOrBase,
|
2009-07-02 03:21:19 +08:00
|
|
|
|
TypeTy *TemplateTypeTy,
|
2008-11-05 12:29:56 +08:00
|
|
|
|
SourceLocation IdLoc,
|
|
|
|
|
SourceLocation LParenLoc,
|
|
|
|
|
ExprTy **Args, unsigned NumArgs,
|
|
|
|
|
SourceLocation *CommaLocs,
|
|
|
|
|
SourceLocation RParenLoc) {
|
2009-06-23 07:20:33 +08:00
|
|
|
|
if (!ConstructorD)
|
|
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-24 19:57:43 +08:00
|
|
|
|
AdjustDeclIfTemplate(ConstructorD);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
|
CXXConstructorDecl *Constructor
|
2009-03-29 03:18:32 +08:00
|
|
|
|
= dyn_cast<CXXConstructorDecl>(ConstructorD.getAs<Decl>());
|
2008-11-05 12:29:56 +08:00
|
|
|
|
if (!Constructor) {
|
|
|
|
|
// The user wrote a constructor initializer on a function that is
|
|
|
|
|
// not a C++ constructor. Ignore the error for now, because we may
|
|
|
|
|
// have more member initializers coming; we'll diagnose it just
|
|
|
|
|
// once in ActOnMemInitializers.
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CXXRecordDecl *ClassDecl = Constructor->getParent();
|
|
|
|
|
|
|
|
|
|
// C++ [class.base.init]p2:
|
|
|
|
|
// Names in a mem-initializer-id are looked up in the scope of the
|
|
|
|
|
// constructor’s class and, if not found in that scope, are looked
|
|
|
|
|
// up in the scope containing the constructor’s
|
|
|
|
|
// definition. [Note: if the constructor’s class contains a member
|
|
|
|
|
// with the same name as a direct or virtual base class of the
|
|
|
|
|
// class, a mem-initializer-id naming the member or base class and
|
|
|
|
|
// composed of a single identifier refers to the class member. A
|
|
|
|
|
// mem-initializer-id for the hidden base class may be specified
|
|
|
|
|
// using a qualified name. ]
|
2009-07-02 03:21:19 +08:00
|
|
|
|
if (!SS.getScopeRep() && !TemplateTypeTy) {
|
2009-07-01 07:26:25 +08:00
|
|
|
|
// Look for a member, first.
|
|
|
|
|
FieldDecl *Member = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
DeclContext::lookup_result Result
|
2009-07-01 07:26:25 +08:00
|
|
|
|
= ClassDecl->lookup(MemberOrBase);
|
|
|
|
|
if (Result.first != Result.second)
|
|
|
|
|
Member = dyn_cast<FieldDecl>(*Result.first);
|
|
|
|
|
|
|
|
|
|
// FIXME: Handle members of an anonymous union.
|
|
|
|
|
|
2009-07-30 03:44:27 +08:00
|
|
|
|
if (Member)
|
|
|
|
|
return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc,
|
|
|
|
|
RParenLoc);
|
2008-11-05 12:29:56 +08:00
|
|
|
|
}
|
|
|
|
|
// It didn't name a member, so see if it names a class.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
TypeTy *BaseTy = TemplateTypeTy ? TemplateTypeTy
|
2009-07-02 03:21:19 +08:00
|
|
|
|
: getTypeName(*MemberOrBase, IdLoc, S, &SS);
|
2008-11-05 12:29:56 +08:00
|
|
|
|
if (!BaseTy)
|
2008-11-19 16:23:25 +08:00
|
|
|
|
return Diag(IdLoc, diag::err_mem_init_not_member_or_class)
|
|
|
|
|
<< MemberOrBase << SourceRange(IdLoc, RParenLoc);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-19 09:28:28 +08:00
|
|
|
|
QualType BaseType = GetTypeFromParser(BaseTy);
|
2008-11-05 12:29:56 +08:00
|
|
|
|
|
2009-07-30 03:44:27 +08:00
|
|
|
|
return BuildBaseInitializer(BaseType, (Expr **)Args, NumArgs, IdLoc,
|
|
|
|
|
RParenLoc, ClassDecl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Sema::MemInitResult
|
|
|
|
|
Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
|
|
|
|
|
unsigned NumArgs, SourceLocation IdLoc,
|
|
|
|
|
SourceLocation RParenLoc) {
|
|
|
|
|
bool HasDependentArg = false;
|
|
|
|
|
for (unsigned i = 0; i < NumArgs; i++)
|
|
|
|
|
HasDependentArg |= Args[i]->isTypeDependent();
|
|
|
|
|
|
|
|
|
|
CXXConstructorDecl *C = 0;
|
|
|
|
|
QualType FieldType = Member->getType();
|
|
|
|
|
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
|
|
|
|
|
FieldType = Array->getElementType();
|
|
|
|
|
if (FieldType->isDependentType()) {
|
|
|
|
|
// Can't check init for dependent type.
|
2009-07-30 05:53:49 +08:00
|
|
|
|
} else if (FieldType->getAs<RecordType>()) {
|
2009-09-10 07:08:42 +08:00
|
|
|
|
if (!HasDependentArg) {
|
|
|
|
|
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
|
|
|
|
|
|
|
|
|
|
C = PerformInitializationByConstructor(FieldType,
|
|
|
|
|
MultiExprArg(*this,
|
|
|
|
|
(void**)Args,
|
|
|
|
|
NumArgs),
|
|
|
|
|
IdLoc,
|
|
|
|
|
SourceRange(IdLoc, RParenLoc),
|
|
|
|
|
Member->getDeclName(), IK_Direct,
|
|
|
|
|
ConstructorArgs);
|
|
|
|
|
|
|
|
|
|
if (C) {
|
|
|
|
|
// Take over the constructor arguments as our own.
|
|
|
|
|
NumArgs = ConstructorArgs.size();
|
|
|
|
|
Args = (Expr **)ConstructorArgs.take();
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-03 01:10:17 +08:00
|
|
|
|
} else if (NumArgs != 1 && NumArgs != 0) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
return Diag(IdLoc, diag::err_mem_initializer_mismatch)
|
2009-07-30 03:44:27 +08:00
|
|
|
|
<< Member->getDeclName() << SourceRange(IdLoc, RParenLoc);
|
|
|
|
|
} else if (!HasDependentArg) {
|
2009-09-03 01:10:17 +08:00
|
|
|
|
Expr *NewExp;
|
|
|
|
|
if (NumArgs == 0) {
|
2009-09-04 03:36:46 +08:00
|
|
|
|
if (FieldType->isReferenceType()) {
|
|
|
|
|
Diag(IdLoc, diag::err_null_intialized_reference_member)
|
|
|
|
|
<< Member->getDeclName();
|
|
|
|
|
return Diag(Member->getLocation(), diag::note_declared_at);
|
|
|
|
|
}
|
2009-09-03 01:10:17 +08:00
|
|
|
|
NewExp = new (Context) CXXZeroInitValueExpr(FieldType, IdLoc, RParenLoc);
|
|
|
|
|
NumArgs = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
NewExp = (Expr*)Args[0];
|
2009-07-30 03:44:27 +08:00
|
|
|
|
if (PerformCopyInitialization(NewExp, FieldType, "passing"))
|
|
|
|
|
return true;
|
|
|
|
|
Args[0] = NewExp;
|
2008-11-05 12:29:56 +08:00
|
|
|
|
}
|
2009-07-30 03:44:27 +08:00
|
|
|
|
// FIXME: Perform direct initialization of the member.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
return new (Context) CXXBaseOrMemberInitializer(Member, (Expr **)Args,
|
2009-08-29 09:31:33 +08:00
|
|
|
|
NumArgs, C, IdLoc, RParenLoc);
|
2009-07-30 03:44:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Sema::MemInitResult
|
|
|
|
|
Sema::BuildBaseInitializer(QualType BaseType, Expr **Args,
|
|
|
|
|
unsigned NumArgs, SourceLocation IdLoc,
|
|
|
|
|
SourceLocation RParenLoc, CXXRecordDecl *ClassDecl) {
|
|
|
|
|
bool HasDependentArg = false;
|
|
|
|
|
for (unsigned i = 0; i < NumArgs; i++)
|
|
|
|
|
HasDependentArg |= Args[i]->isTypeDependent();
|
|
|
|
|
|
|
|
|
|
if (!BaseType->isDependentType()) {
|
|
|
|
|
if (!BaseType->isRecordType())
|
|
|
|
|
return Diag(IdLoc, diag::err_base_init_does_not_name_class)
|
|
|
|
|
<< BaseType << SourceRange(IdLoc, RParenLoc);
|
|
|
|
|
|
|
|
|
|
// C++ [class.base.init]p2:
|
|
|
|
|
// [...] Unless the mem-initializer-id names a nonstatic data
|
|
|
|
|
// member of the constructor’s class or a direct or virtual base
|
|
|
|
|
// of that class, the mem-initializer is ill-formed. A
|
|
|
|
|
// mem-initializer-list can initialize a base class using any
|
|
|
|
|
// name that denotes that base class type.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-07-30 03:44:27 +08:00
|
|
|
|
// First, check for a direct base class.
|
|
|
|
|
const CXXBaseSpecifier *DirectBaseSpec = 0;
|
|
|
|
|
for (CXXRecordDecl::base_class_const_iterator Base =
|
|
|
|
|
ClassDecl->bases_begin(); Base != ClassDecl->bases_end(); ++Base) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (Context.getCanonicalType(BaseType).getUnqualifiedType() ==
|
2009-07-30 03:44:27 +08:00
|
|
|
|
Context.getCanonicalType(Base->getType()).getUnqualifiedType()) {
|
|
|
|
|
// We found a direct base of this type. That's what we're
|
|
|
|
|
// initializing.
|
|
|
|
|
DirectBaseSpec = &*Base;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-07-30 03:44:27 +08:00
|
|
|
|
// Check for a virtual base class.
|
|
|
|
|
// FIXME: We might be able to short-circuit this if we know in advance that
|
|
|
|
|
// there are no virtual bases.
|
|
|
|
|
const CXXBaseSpecifier *VirtualBaseSpec = 0;
|
|
|
|
|
if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) {
|
|
|
|
|
// We haven't found a base yet; search the class hierarchy for a
|
|
|
|
|
// virtual base class.
|
|
|
|
|
BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
|
|
|
|
|
/*DetectVirtual=*/false);
|
|
|
|
|
if (IsDerivedFrom(Context.getTypeDeclType(ClassDecl), BaseType, Paths)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
for (BasePaths::paths_iterator Path = Paths.begin();
|
2009-07-30 03:44:27 +08:00
|
|
|
|
Path != Paths.end(); ++Path) {
|
|
|
|
|
if (Path->back().Base->isVirtual()) {
|
|
|
|
|
VirtualBaseSpec = Path->back().Base;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2008-11-05 12:29:56 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-07-30 03:44:27 +08:00
|
|
|
|
|
|
|
|
|
// C++ [base.class.init]p2:
|
|
|
|
|
// If a mem-initializer-id is ambiguous because it designates both
|
|
|
|
|
// a direct non-virtual base class and an inherited virtual base
|
|
|
|
|
// class, the mem-initializer is ill-formed.
|
|
|
|
|
if (DirectBaseSpec && VirtualBaseSpec)
|
|
|
|
|
return Diag(IdLoc, diag::err_base_init_direct_and_virtual)
|
|
|
|
|
<< BaseType << SourceRange(IdLoc, RParenLoc);
|
|
|
|
|
// C++ [base.class.init]p2:
|
|
|
|
|
// Unless the mem-initializer-id names a nonstatic data membeer of the
|
|
|
|
|
// constructor's class ot a direst or virtual base of that class, the
|
|
|
|
|
// mem-initializer is ill-formed.
|
|
|
|
|
if (!DirectBaseSpec && !VirtualBaseSpec)
|
|
|
|
|
return Diag(IdLoc, diag::err_not_direct_base_or_virtual)
|
|
|
|
|
<< BaseType << ClassDecl->getNameAsCString()
|
|
|
|
|
<< SourceRange(IdLoc, RParenLoc);
|
2008-11-05 12:29:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-07-23 08:42:24 +08:00
|
|
|
|
CXXConstructorDecl *C = 0;
|
2009-07-30 03:44:27 +08:00
|
|
|
|
if (!BaseType->isDependentType() && !HasDependentArg) {
|
|
|
|
|
DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(
|
|
|
|
|
Context.getCanonicalType(BaseType));
|
2009-09-10 07:08:42 +08:00
|
|
|
|
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
|
|
|
|
|
|
|
|
|
|
C = PerformInitializationByConstructor(BaseType,
|
|
|
|
|
MultiExprArg(*this,
|
|
|
|
|
(void**)Args, NumArgs),
|
2009-09-09 23:08:12 +08:00
|
|
|
|
IdLoc, SourceRange(IdLoc, RParenLoc),
|
2009-09-10 07:08:42 +08:00
|
|
|
|
Name, IK_Direct,
|
|
|
|
|
ConstructorArgs);
|
|
|
|
|
if (C) {
|
|
|
|
|
// Take over the constructor arguments as our own.
|
|
|
|
|
NumArgs = ConstructorArgs.size();
|
|
|
|
|
Args = (Expr **)ConstructorArgs.take();
|
|
|
|
|
}
|
2009-07-30 03:44:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
return new (Context) CXXBaseOrMemberInitializer(BaseType, (Expr **)Args,
|
2009-08-29 09:31:33 +08:00
|
|
|
|
NumArgs, C, IdLoc, RParenLoc);
|
2008-11-05 12:29:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-09-04 03:36:46 +08:00
|
|
|
|
void
|
|
|
|
|
Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
|
|
|
|
|
CXXBaseOrMemberInitializer **Initializers,
|
|
|
|
|
unsigned NumInitializers,
|
2009-09-09 23:08:12 +08:00
|
|
|
|
llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases,
|
2009-09-04 03:36:46 +08:00
|
|
|
|
llvm::SmallVectorImpl<FieldDecl *>&Fields) {
|
|
|
|
|
// We need to build the initializer AST according to order of construction
|
|
|
|
|
// and not what user specified in the Initializers list.
|
|
|
|
|
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Constructor->getDeclContext());
|
|
|
|
|
llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToInit;
|
|
|
|
|
llvm::DenseMap<const void *, CXXBaseOrMemberInitializer*> AllBaseFields;
|
|
|
|
|
bool HasDependentBaseInit = false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-04 03:36:46 +08:00
|
|
|
|
for (unsigned i = 0; i < NumInitializers; i++) {
|
|
|
|
|
CXXBaseOrMemberInitializer *Member = Initializers[i];
|
|
|
|
|
if (Member->isBaseInitializer()) {
|
|
|
|
|
if (Member->getBaseClass()->isDependentType())
|
|
|
|
|
HasDependentBaseInit = true;
|
|
|
|
|
AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
|
|
|
|
|
} else {
|
|
|
|
|
AllBaseFields[Member->getMember()] = Member;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-04 03:36:46 +08:00
|
|
|
|
if (HasDependentBaseInit) {
|
|
|
|
|
// FIXME. This does not preserve the ordering of the initializers.
|
|
|
|
|
// Try (with -Wreorder)
|
|
|
|
|
// template<class X> struct A {};
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// template<class X> struct B : A<X> {
|
|
|
|
|
// B() : x1(10), A<X>() {}
|
2009-09-04 03:36:46 +08:00
|
|
|
|
// int x1;
|
|
|
|
|
// };
|
|
|
|
|
// B<int> x;
|
|
|
|
|
// On seeing one dependent type, we should essentially exit this routine
|
|
|
|
|
// while preserving user-declared initializer list. When this routine is
|
|
|
|
|
// called during instantiatiation process, this routine will rebuild the
|
|
|
|
|
// oderdered initializer list correctly.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-04 03:36:46 +08:00
|
|
|
|
// If we have a dependent base initialization, we can't determine the
|
|
|
|
|
// association between initializers and bases; just dump the known
|
|
|
|
|
// initializers into the list, and don't try to deal with other bases.
|
|
|
|
|
for (unsigned i = 0; i < NumInitializers; i++) {
|
|
|
|
|
CXXBaseOrMemberInitializer *Member = Initializers[i];
|
|
|
|
|
if (Member->isBaseInitializer())
|
|
|
|
|
AllToInit.push_back(Member);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Push virtual bases before others.
|
|
|
|
|
for (CXXRecordDecl::base_class_iterator VBase =
|
|
|
|
|
ClassDecl->vbases_begin(),
|
|
|
|
|
E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
|
|
|
|
|
if (VBase->getType()->isDependentType())
|
|
|
|
|
continue;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CXXBaseOrMemberInitializer *Value =
|
2009-09-04 05:32:41 +08:00
|
|
|
|
AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CXXRecordDecl *BaseDecl =
|
2009-09-04 05:32:41 +08:00
|
|
|
|
cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
|
|
|
|
|
assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null");
|
|
|
|
|
if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context))
|
|
|
|
|
MarkDeclarationReferenced(Value->getSourceLocation(), Ctor);
|
2009-09-04 03:36:46 +08:00
|
|
|
|
AllToInit.push_back(Value);
|
2009-09-04 05:32:41 +08:00
|
|
|
|
}
|
2009-09-04 03:36:46 +08:00
|
|
|
|
else {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CXXRecordDecl *VBaseDecl =
|
2009-09-04 03:36:46 +08:00
|
|
|
|
cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
|
|
|
|
|
assert(VBaseDecl && "setBaseOrMemberInitializers - VBaseDecl null");
|
2009-09-04 05:32:41 +08:00
|
|
|
|
CXXConstructorDecl *Ctor = VBaseDecl->getDefaultConstructor(Context);
|
|
|
|
|
if (!Ctor)
|
2009-09-04 03:36:46 +08:00
|
|
|
|
Bases.push_back(VBase);
|
2009-09-04 05:32:41 +08:00
|
|
|
|
else
|
|
|
|
|
MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CXXBaseOrMemberInitializer *Member =
|
2009-09-04 03:36:46 +08:00
|
|
|
|
new (Context) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0,
|
2009-09-04 05:32:41 +08:00
|
|
|
|
Ctor,
|
2009-09-04 03:36:46 +08:00
|
|
|
|
SourceLocation(),
|
|
|
|
|
SourceLocation());
|
|
|
|
|
AllToInit.push_back(Member);
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-04 03:36:46 +08:00
|
|
|
|
for (CXXRecordDecl::base_class_iterator Base =
|
|
|
|
|
ClassDecl->bases_begin(),
|
|
|
|
|
E = ClassDecl->bases_end(); Base != E; ++Base) {
|
|
|
|
|
// Virtuals are in the virtual base list and already constructed.
|
|
|
|
|
if (Base->isVirtual())
|
|
|
|
|
continue;
|
|
|
|
|
// Skip dependent types.
|
|
|
|
|
if (Base->getType()->isDependentType())
|
|
|
|
|
continue;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CXXBaseOrMemberInitializer *Value =
|
2009-09-04 05:32:41 +08:00
|
|
|
|
AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CXXRecordDecl *BaseDecl =
|
2009-09-04 05:32:41 +08:00
|
|
|
|
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
|
|
|
|
assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null");
|
|
|
|
|
if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context))
|
|
|
|
|
MarkDeclarationReferenced(Value->getSourceLocation(), Ctor);
|
2009-09-04 03:36:46 +08:00
|
|
|
|
AllToInit.push_back(Value);
|
2009-09-04 05:32:41 +08:00
|
|
|
|
}
|
2009-09-04 03:36:46 +08:00
|
|
|
|
else {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CXXRecordDecl *BaseDecl =
|
2009-09-04 05:32:41 +08:00
|
|
|
|
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
2009-09-04 03:36:46 +08:00
|
|
|
|
assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null");
|
2009-09-04 05:32:41 +08:00
|
|
|
|
CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context);
|
|
|
|
|
if (!Ctor)
|
2009-09-04 03:36:46 +08:00
|
|
|
|
Bases.push_back(Base);
|
2009-09-04 05:32:41 +08:00
|
|
|
|
else
|
|
|
|
|
MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CXXBaseOrMemberInitializer *Member =
|
2009-09-04 03:36:46 +08:00
|
|
|
|
new (Context) CXXBaseOrMemberInitializer(Base->getType(), 0, 0,
|
|
|
|
|
BaseDecl->getDefaultConstructor(Context),
|
|
|
|
|
SourceLocation(),
|
|
|
|
|
SourceLocation());
|
|
|
|
|
AllToInit.push_back(Member);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-04 03:36:46 +08:00
|
|
|
|
// non-static data members.
|
|
|
|
|
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
|
|
|
|
|
E = ClassDecl->field_end(); Field != E; ++Field) {
|
|
|
|
|
if ((*Field)->isAnonymousStructOrUnion()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (const RecordType *FieldClassType =
|
2009-09-04 03:36:46 +08:00
|
|
|
|
Field->getType()->getAs<RecordType>()) {
|
|
|
|
|
CXXRecordDecl *FieldClassDecl
|
|
|
|
|
= cast<CXXRecordDecl>(FieldClassType->getDecl());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),
|
2009-09-04 03:36:46 +08:00
|
|
|
|
EA = FieldClassDecl->field_end(); FA != EA; FA++) {
|
|
|
|
|
if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*FA)) {
|
|
|
|
|
// 'Member' is the anonymous union field and 'AnonUnionMember' is
|
|
|
|
|
// set to the anonymous union data member used in the initializer
|
|
|
|
|
// list.
|
|
|
|
|
Value->setMember(*Field);
|
|
|
|
|
Value->setAnonUnionMember(*FA);
|
|
|
|
|
AllToInit.push_back(Value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*Field)) {
|
2009-09-04 05:32:41 +08:00
|
|
|
|
QualType FT = (*Field)->getType();
|
|
|
|
|
if (const RecordType* RT = FT->getAs<RecordType>()) {
|
|
|
|
|
CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RT->getDecl());
|
|
|
|
|
assert(FieldRecDecl && "setBaseOrMemberInitializers - BaseDecl null");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CXXConstructorDecl *Ctor =
|
2009-09-04 05:32:41 +08:00
|
|
|
|
FieldRecDecl->getDefaultConstructor(Context))
|
|
|
|
|
MarkDeclarationReferenced(Value->getSourceLocation(), Ctor);
|
|
|
|
|
}
|
2009-09-04 03:36:46 +08:00
|
|
|
|
AllToInit.push_back(Value);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-04 03:36:46 +08:00
|
|
|
|
QualType FT = Context.getBaseElementType((*Field)->getType());
|
|
|
|
|
if (const RecordType* RT = FT->getAs<RecordType>()) {
|
|
|
|
|
CXXConstructorDecl *Ctor =
|
|
|
|
|
cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context);
|
|
|
|
|
if (!Ctor && !FT->isDependentType())
|
|
|
|
|
Fields.push_back(*Field);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CXXBaseOrMemberInitializer *Member =
|
2009-09-04 03:36:46 +08:00
|
|
|
|
new (Context) CXXBaseOrMemberInitializer((*Field), 0, 0,
|
|
|
|
|
Ctor,
|
|
|
|
|
SourceLocation(),
|
|
|
|
|
SourceLocation());
|
|
|
|
|
AllToInit.push_back(Member);
|
2009-09-04 05:32:41 +08:00
|
|
|
|
if (Ctor)
|
|
|
|
|
MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
|
2009-09-04 03:36:46 +08:00
|
|
|
|
if (FT.isConstQualified() && (!Ctor || Ctor->isTrivial())) {
|
|
|
|
|
Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
|
|
|
|
|
<< Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getDeclName();
|
|
|
|
|
Diag((*Field)->getLocation(), diag::note_declared_at);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (FT->isReferenceType()) {
|
|
|
|
|
Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
|
|
|
|
|
<< Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getDeclName();
|
|
|
|
|
Diag((*Field)->getLocation(), diag::note_declared_at);
|
|
|
|
|
}
|
|
|
|
|
else if (FT.isConstQualified()) {
|
|
|
|
|
Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
|
|
|
|
|
<< Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getDeclName();
|
|
|
|
|
Diag((*Field)->getLocation(), diag::note_declared_at);
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-04 03:36:46 +08:00
|
|
|
|
NumInitializers = AllToInit.size();
|
|
|
|
|
if (NumInitializers > 0) {
|
|
|
|
|
Constructor->setNumBaseOrMemberInitializers(NumInitializers);
|
|
|
|
|
CXXBaseOrMemberInitializer **baseOrMemberInitializers =
|
|
|
|
|
new (Context) CXXBaseOrMemberInitializer*[NumInitializers];
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-04 03:36:46 +08:00
|
|
|
|
Constructor->setBaseOrMemberInitializers(baseOrMemberInitializers);
|
|
|
|
|
for (unsigned Idx = 0; Idx < NumInitializers; ++Idx)
|
|
|
|
|
baseOrMemberInitializers[Idx] = AllToInit[Idx];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-24 07:32:59 +08:00
|
|
|
|
void
|
|
|
|
|
Sema::BuildBaseOrMemberInitializers(ASTContext &C,
|
|
|
|
|
CXXConstructorDecl *Constructor,
|
|
|
|
|
CXXBaseOrMemberInitializer **Initializers,
|
|
|
|
|
unsigned NumInitializers
|
|
|
|
|
) {
|
|
|
|
|
llvm::SmallVector<CXXBaseSpecifier *, 4>Bases;
|
|
|
|
|
llvm::SmallVector<FieldDecl *, 4>Members;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
|
setBaseOrMemberInitializers(Constructor,
|
2009-09-04 03:36:46 +08:00
|
|
|
|
Initializers, NumInitializers, Bases, Members);
|
2009-07-24 07:32:59 +08:00
|
|
|
|
for (unsigned int i = 0; i < Bases.size(); i++)
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(Bases[i]->getSourceRange().getBegin(),
|
2009-07-24 07:32:59 +08:00
|
|
|
|
diag::err_missing_default_constructor) << 0 << Bases[i]->getType();
|
|
|
|
|
for (unsigned int i = 0; i < Members.size(); i++)
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(Members[i]->getLocation(), diag::err_missing_default_constructor)
|
2009-07-24 07:32:59 +08:00
|
|
|
|
<< 1 << Members[i]->getType();
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-22 03:28:10 +08:00
|
|
|
|
static void *GetKeyForTopLevelField(FieldDecl *Field) {
|
|
|
|
|
// For anonymous unions, use the class declaration as the key.
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
|
2009-07-22 03:28:10 +08:00
|
|
|
|
if (RT->getDecl()->isAnonymousStructOrUnion())
|
|
|
|
|
return static_cast<void *>(RT->getDecl());
|
|
|
|
|
}
|
|
|
|
|
return static_cast<void *>(Field);
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-01 14:22:14 +08:00
|
|
|
|
static void *GetKeyForBase(QualType BaseType) {
|
|
|
|
|
if (const RecordType *RT = BaseType->getAs<RecordType>())
|
|
|
|
|
return (void *)RT;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-01 14:22:14 +08:00
|
|
|
|
assert(0 && "Unexpected base type!");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member,
|
2009-09-01 14:22:14 +08:00
|
|
|
|
bool MemberMaybeAnon = false) {
|
2009-07-22 03:28:10 +08:00
|
|
|
|
// For fields injected into the class via declaration of an anonymous union,
|
|
|
|
|
// use its anonymous union class declaration as the unique key.
|
2009-09-01 14:22:14 +08:00
|
|
|
|
if (Member->isMemberInitializer()) {
|
|
|
|
|
FieldDecl *Field = Member->getMember();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-12 02:49:54 +08:00
|
|
|
|
// After BuildBaseOrMemberInitializers call, Field is the anonymous union
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// data member of the class. Data member used in the initializer list is
|
2009-08-12 02:49:54 +08:00
|
|
|
|
// in AnonUnionMember field.
|
|
|
|
|
if (MemberMaybeAnon && Field->isAnonymousStructOrUnion())
|
|
|
|
|
Field = Member->getAnonUnionMember();
|
2009-07-22 03:28:10 +08:00
|
|
|
|
if (Field->getDeclContext()->isRecord()) {
|
|
|
|
|
RecordDecl *RD = cast<RecordDecl>(Field->getDeclContext());
|
|
|
|
|
if (RD->isAnonymousStructOrUnion())
|
|
|
|
|
return static_cast<void *>(RD);
|
|
|
|
|
}
|
|
|
|
|
return static_cast<void *>(Field);
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-01 14:22:14 +08:00
|
|
|
|
return GetKeyForBase(QualType(Member->getBaseClass(), 0));
|
2009-07-22 03:28:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
|
2009-03-25 10:58:17 +08:00
|
|
|
|
SourceLocation ColonLoc,
|
|
|
|
|
MemInitTy **MemInits, unsigned NumMemInits) {
|
2009-06-23 07:20:33 +08:00
|
|
|
|
if (!ConstructorDecl)
|
|
|
|
|
return;
|
2009-08-24 19:57:43 +08:00
|
|
|
|
|
|
|
|
|
AdjustDeclIfTemplate(ConstructorDecl);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
|
CXXConstructorDecl *Constructor
|
2009-06-23 07:20:33 +08:00
|
|
|
|
= dyn_cast<CXXConstructorDecl>(ConstructorDecl.getAs<Decl>());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-25 10:58:17 +08:00
|
|
|
|
if (!Constructor) {
|
|
|
|
|
Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-27 13:57:30 +08:00
|
|
|
|
if (!Constructor->isDependentContext()) {
|
|
|
|
|
llvm::DenseMap<void*, CXXBaseOrMemberInitializer *>Members;
|
|
|
|
|
bool err = false;
|
|
|
|
|
for (unsigned i = 0; i < NumMemInits; i++) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CXXBaseOrMemberInitializer *Member =
|
2009-08-27 13:57:30 +08:00
|
|
|
|
static_cast<CXXBaseOrMemberInitializer*>(MemInits[i]);
|
|
|
|
|
void *KeyToMember = GetKeyForMember(Member);
|
|
|
|
|
CXXBaseOrMemberInitializer *&PrevMember = Members[KeyToMember];
|
|
|
|
|
if (!PrevMember) {
|
|
|
|
|
PrevMember = Member;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (FieldDecl *Field = Member->getMember())
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(Member->getSourceLocation(),
|
2009-08-27 13:57:30 +08:00
|
|
|
|
diag::error_multiple_mem_initialization)
|
|
|
|
|
<< Field->getNameAsString();
|
|
|
|
|
else {
|
|
|
|
|
Type *BaseClass = Member->getBaseClass();
|
|
|
|
|
assert(BaseClass && "ActOnMemInitializers - neither field or base");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(Member->getSourceLocation(),
|
2009-08-27 13:57:30 +08:00
|
|
|
|
diag::error_multiple_base_initialization)
|
|
|
|
|
<< BaseClass->getDesugaredType(true);
|
|
|
|
|
}
|
|
|
|
|
Diag(PrevMember->getSourceLocation(), diag::note_previous_initializer)
|
|
|
|
|
<< 0;
|
|
|
|
|
err = true;
|
2009-06-30 06:33:26 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-27 13:57:30 +08:00
|
|
|
|
if (err)
|
|
|
|
|
return;
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-27 13:45:01 +08:00
|
|
|
|
BuildBaseOrMemberInitializers(Context, Constructor,
|
2009-09-09 23:08:12 +08:00
|
|
|
|
reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits),
|
2009-07-24 07:32:59 +08:00
|
|
|
|
NumMemInits);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-27 13:57:30 +08:00
|
|
|
|
if (Constructor->isDependentContext())
|
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
|
if (Diags.getDiagnosticLevel(diag::warn_base_initialized) ==
|
2009-08-27 13:45:01 +08:00
|
|
|
|
Diagnostic::Ignored &&
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diags.getDiagnosticLevel(diag::warn_field_initialized) ==
|
2009-08-27 13:45:01 +08:00
|
|
|
|
Diagnostic::Ignored)
|
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-27 13:45:01 +08:00
|
|
|
|
// Also issue warning if order of ctor-initializer list does not match order
|
|
|
|
|
// of 1) base class declarations and 2) order of non-static data members.
|
|
|
|
|
llvm::SmallVector<const void*, 32> AllBaseOrMembers;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-27 13:45:01 +08:00
|
|
|
|
CXXRecordDecl *ClassDecl
|
|
|
|
|
= cast<CXXRecordDecl>(Constructor->getDeclContext());
|
|
|
|
|
// Push virtual bases before others.
|
|
|
|
|
for (CXXRecordDecl::base_class_iterator VBase =
|
|
|
|
|
ClassDecl->vbases_begin(),
|
|
|
|
|
E = ClassDecl->vbases_end(); VBase != E; ++VBase)
|
2009-09-01 14:22:14 +08:00
|
|
|
|
AllBaseOrMembers.push_back(GetKeyForBase(VBase->getType()));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-27 13:45:01 +08:00
|
|
|
|
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
|
|
|
|
|
E = ClassDecl->bases_end(); Base != E; ++Base) {
|
|
|
|
|
// Virtuals are alread in the virtual base list and are constructed
|
|
|
|
|
// first.
|
|
|
|
|
if (Base->isVirtual())
|
|
|
|
|
continue;
|
2009-09-01 14:22:14 +08:00
|
|
|
|
AllBaseOrMembers.push_back(GetKeyForBase(Base->getType()));
|
2009-08-27 13:45:01 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-27 13:45:01 +08:00
|
|
|
|
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
|
|
|
|
|
E = ClassDecl->field_end(); Field != E; ++Field)
|
|
|
|
|
AllBaseOrMembers.push_back(GetKeyForTopLevelField(*Field));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-27 13:45:01 +08:00
|
|
|
|
int Last = AllBaseOrMembers.size();
|
|
|
|
|
int curIndex = 0;
|
|
|
|
|
CXXBaseOrMemberInitializer *PrevMember = 0;
|
|
|
|
|
for (unsigned i = 0; i < NumMemInits; i++) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CXXBaseOrMemberInitializer *Member =
|
2009-08-27 13:45:01 +08:00
|
|
|
|
static_cast<CXXBaseOrMemberInitializer*>(MemInits[i]);
|
|
|
|
|
void *MemberInCtorList = GetKeyForMember(Member, true);
|
|
|
|
|
|
|
|
|
|
for (; curIndex < Last; curIndex++)
|
|
|
|
|
if (MemberInCtorList == AllBaseOrMembers[curIndex])
|
|
|
|
|
break;
|
|
|
|
|
if (curIndex == Last) {
|
|
|
|
|
assert(PrevMember && "Member not in member list?!");
|
|
|
|
|
// Initializer as specified in ctor-initializer list is out of order.
|
|
|
|
|
// Issue a warning diagnostic.
|
|
|
|
|
if (PrevMember->isBaseInitializer()) {
|
|
|
|
|
// Diagnostics is for an initialized base class.
|
|
|
|
|
Type *BaseClass = PrevMember->getBaseClass();
|
|
|
|
|
Diag(PrevMember->getSourceLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
|
diag::warn_base_initialized)
|
2009-08-27 13:45:01 +08:00
|
|
|
|
<< BaseClass->getDesugaredType(true);
|
|
|
|
|
} else {
|
|
|
|
|
FieldDecl *Field = PrevMember->getMember();
|
|
|
|
|
Diag(PrevMember->getSourceLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
|
diag::warn_field_initialized)
|
2009-08-27 13:45:01 +08:00
|
|
|
|
<< Field->getNameAsString();
|
2009-07-10 03:59:47 +08:00
|
|
|
|
}
|
2009-08-27 13:45:01 +08:00
|
|
|
|
// Also the note!
|
|
|
|
|
if (FieldDecl *Field = Member->getMember())
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(Member->getSourceLocation(),
|
2009-08-27 13:45:01 +08:00
|
|
|
|
diag::note_fieldorbase_initialized_here) << 0
|
|
|
|
|
<< Field->getNameAsString();
|
|
|
|
|
else {
|
|
|
|
|
Type *BaseClass = Member->getBaseClass();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(Member->getSourceLocation(),
|
2009-08-27 13:45:01 +08:00
|
|
|
|
diag::note_fieldorbase_initialized_here) << 1
|
|
|
|
|
<< BaseClass->getDesugaredType(true);
|
|
|
|
|
}
|
|
|
|
|
for (curIndex = 0; curIndex < Last; curIndex++)
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (MemberInCtorList == AllBaseOrMembers[curIndex])
|
2009-08-27 13:45:01 +08:00
|
|
|
|
break;
|
2009-07-10 03:59:47 +08:00
|
|
|
|
}
|
2009-08-27 13:45:01 +08:00
|
|
|
|
PrevMember = Member;
|
2009-07-10 03:59:47 +08:00
|
|
|
|
}
|
2009-03-25 10:58:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-09-04 07:18:17 +08:00
|
|
|
|
void
|
|
|
|
|
Sema::computeBaseOrMembersToDestroy(CXXDestructorDecl *Destructor) {
|
|
|
|
|
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Destructor->getDeclContext());
|
|
|
|
|
llvm::SmallVector<uintptr_t, 32> AllToDestruct;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-04 07:18:17 +08:00
|
|
|
|
for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
|
|
|
|
|
E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
|
|
|
|
|
if (VBase->getType()->isDependentType())
|
|
|
|
|
continue;
|
|
|
|
|
// Skip over virtual bases which have trivial destructors.
|
|
|
|
|
CXXRecordDecl *BaseClassDecl
|
|
|
|
|
= cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
|
|
|
|
|
if (BaseClassDecl->hasTrivialDestructor())
|
|
|
|
|
continue;
|
|
|
|
|
if (const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context))
|
2009-09-09 23:08:12 +08:00
|
|
|
|
MarkDeclarationReferenced(Destructor->getLocation(),
|
2009-09-04 07:18:17 +08:00
|
|
|
|
const_cast<CXXDestructorDecl*>(Dtor));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
|
uintptr_t Member =
|
|
|
|
|
reinterpret_cast<uintptr_t>(VBase->getType().getTypePtr())
|
2009-09-04 07:18:17 +08:00
|
|
|
|
| CXXDestructorDecl::VBASE;
|
|
|
|
|
AllToDestruct.push_back(Member);
|
|
|
|
|
}
|
|
|
|
|
for (CXXRecordDecl::base_class_iterator Base =
|
|
|
|
|
ClassDecl->bases_begin(),
|
|
|
|
|
E = ClassDecl->bases_end(); Base != E; ++Base) {
|
|
|
|
|
if (Base->isVirtual())
|
|
|
|
|
continue;
|
|
|
|
|
if (Base->getType()->isDependentType())
|
|
|
|
|
continue;
|
|
|
|
|
// Skip over virtual bases which have trivial destructors.
|
|
|
|
|
CXXRecordDecl *BaseClassDecl
|
|
|
|
|
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
|
|
|
|
if (BaseClassDecl->hasTrivialDestructor())
|
|
|
|
|
continue;
|
|
|
|
|
if (const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context))
|
2009-09-09 23:08:12 +08:00
|
|
|
|
MarkDeclarationReferenced(Destructor->getLocation(),
|
2009-09-04 07:18:17 +08:00
|
|
|
|
const_cast<CXXDestructorDecl*>(Dtor));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
uintptr_t Member =
|
|
|
|
|
reinterpret_cast<uintptr_t>(Base->getType().getTypePtr())
|
2009-09-04 07:18:17 +08:00
|
|
|
|
| CXXDestructorDecl::DRCTNONVBASE;
|
|
|
|
|
AllToDestruct.push_back(Member);
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-04 07:18:17 +08:00
|
|
|
|
// non-static data members.
|
|
|
|
|
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
|
|
|
|
|
E = ClassDecl->field_end(); Field != E; ++Field) {
|
|
|
|
|
QualType FieldType = Context.getBaseElementType((*Field)->getType());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-04 07:18:17 +08:00
|
|
|
|
if (const RecordType* RT = FieldType->getAs<RecordType>()) {
|
|
|
|
|
// Skip over virtual bases which have trivial destructors.
|
|
|
|
|
CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
|
|
|
|
|
if (FieldClassDecl->hasTrivialDestructor())
|
|
|
|
|
continue;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (const CXXDestructorDecl *Dtor =
|
2009-09-04 07:18:17 +08:00
|
|
|
|
FieldClassDecl->getDestructor(Context))
|
2009-09-09 23:08:12 +08:00
|
|
|
|
MarkDeclarationReferenced(Destructor->getLocation(),
|
2009-09-04 07:18:17 +08:00
|
|
|
|
const_cast<CXXDestructorDecl*>(Dtor));
|
|
|
|
|
uintptr_t Member = reinterpret_cast<uintptr_t>(*Field);
|
|
|
|
|
AllToDestruct.push_back(Member);
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-04 07:18:17 +08:00
|
|
|
|
unsigned NumDestructions = AllToDestruct.size();
|
|
|
|
|
if (NumDestructions > 0) {
|
|
|
|
|
Destructor->setNumBaseOrMemberDestructions(NumDestructions);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
uintptr_t *BaseOrMemberDestructions =
|
2009-09-04 07:18:17 +08:00
|
|
|
|
new (Context) uintptr_t [NumDestructions];
|
|
|
|
|
// Insert in reverse order.
|
|
|
|
|
for (int Idx = NumDestructions-1, i=0 ; Idx >= 0; --Idx)
|
|
|
|
|
BaseOrMemberDestructions[i++] = AllToDestruct[Idx];
|
|
|
|
|
Destructor->setBaseOrMemberDestructions(BaseOrMemberDestructions);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-22 06:36:06 +08:00
|
|
|
|
void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {
|
2009-07-16 06:34:08 +08:00
|
|
|
|
if (!CDtorDecl)
|
2009-07-15 02:24:21 +08:00
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-24 19:57:43 +08:00
|
|
|
|
AdjustDeclIfTemplate(CDtorDecl);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
|
if (CXXConstructorDecl *Constructor
|
2009-07-16 06:34:08 +08:00
|
|
|
|
= dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>()))
|
2009-07-24 07:32:59 +08:00
|
|
|
|
BuildBaseOrMemberInitializers(Context,
|
|
|
|
|
Constructor,
|
|
|
|
|
(CXXBaseOrMemberInitializer **)0, 0);
|
2009-07-15 02:24:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-03-22 09:52:17 +08:00
|
|
|
|
namespace {
|
|
|
|
|
/// PureVirtualMethodCollector - traverses a class and its superclasses
|
|
|
|
|
/// and determines if it has any pure virtual methods.
|
|
|
|
|
class VISIBILITY_HIDDEN PureVirtualMethodCollector {
|
|
|
|
|
ASTContext &Context;
|
|
|
|
|
|
2009-03-23 05:28:55 +08:00
|
|
|
|
public:
|
2009-03-22 09:52:17 +08:00
|
|
|
|
typedef llvm::SmallVector<const CXXMethodDecl*, 8> MethodList;
|
2009-03-23 05:28:55 +08:00
|
|
|
|
|
|
|
|
|
private:
|
2009-03-22 09:52:17 +08:00
|
|
|
|
MethodList Methods;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-22 09:52:17 +08:00
|
|
|
|
void Collect(const CXXRecordDecl* RD, MethodList& Methods);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-22 09:52:17 +08:00
|
|
|
|
public:
|
2009-09-09 23:08:12 +08:00
|
|
|
|
PureVirtualMethodCollector(ASTContext &Ctx, const CXXRecordDecl* RD)
|
2009-03-22 09:52:17 +08:00
|
|
|
|
: Context(Ctx) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-22 09:52:17 +08:00
|
|
|
|
MethodList List;
|
|
|
|
|
Collect(RD, List);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-22 09:52:17 +08:00
|
|
|
|
// Copy the temporary list to methods, and make sure to ignore any
|
|
|
|
|
// null entries.
|
|
|
|
|
for (size_t i = 0, e = List.size(); i != e; ++i) {
|
|
|
|
|
if (List[i])
|
|
|
|
|
Methods.push_back(List[i]);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
}
|
2009-03-22 09:52:17 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-23 04:18:17 +08:00
|
|
|
|
bool empty() const { return Methods.empty(); }
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-23 04:18:17 +08:00
|
|
|
|
MethodList::const_iterator methods_begin() { return Methods.begin(); }
|
|
|
|
|
MethodList::const_iterator methods_end() { return Methods.end(); }
|
2009-03-22 09:52:17 +08:00
|
|
|
|
};
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
|
void PureVirtualMethodCollector::Collect(const CXXRecordDecl* RD,
|
2009-03-22 09:52:17 +08:00
|
|
|
|
MethodList& Methods) {
|
|
|
|
|
// First, collect the pure virtual methods for the base classes.
|
|
|
|
|
for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(),
|
|
|
|
|
BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base) {
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const RecordType *RT = Base->getType()->getAs<RecordType>()) {
|
2009-03-29 13:01:10 +08:00
|
|
|
|
const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl());
|
2009-03-22 09:52:17 +08:00
|
|
|
|
if (BaseDecl && BaseDecl->isAbstract())
|
|
|
|
|
Collect(BaseDecl, Methods);
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-22 09:52:17 +08:00
|
|
|
|
// Next, zero out any pure virtual methods that this class overrides.
|
2009-05-17 08:00:05 +08:00
|
|
|
|
typedef llvm::SmallPtrSet<const CXXMethodDecl*, 4> MethodSetTy;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-05-17 08:00:05 +08:00
|
|
|
|
MethodSetTy OverriddenMethods;
|
|
|
|
|
size_t MethodsSize = Methods.size();
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
for (RecordDecl::decl_iterator i = RD->decls_begin(), e = RD->decls_end();
|
2009-03-22 09:52:17 +08:00
|
|
|
|
i != e; ++i) {
|
2009-05-17 08:00:05 +08:00
|
|
|
|
// Traverse the record, looking for methods.
|
2009-03-22 09:52:17 +08:00
|
|
|
|
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*i)) {
|
2009-07-08 04:29:57 +08:00
|
|
|
|
// If the method is pure virtual, add it to the methods vector.
|
2009-05-17 08:00:05 +08:00
|
|
|
|
if (MD->isPure()) {
|
2009-03-22 09:52:17 +08:00
|
|
|
|
Methods.push_back(MD);
|
2009-05-17 08:00:05 +08:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-05-17 08:00:05 +08:00
|
|
|
|
// Otherwise, record all the overridden methods in our set.
|
|
|
|
|
for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
|
|
|
|
|
E = MD->end_overridden_methods(); I != E; ++I) {
|
|
|
|
|
// Keep track of the overridden methods.
|
|
|
|
|
OverriddenMethods.insert(*I);
|
|
|
|
|
}
|
2009-03-22 09:52:17 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
|
// Now go through the methods and zero out all the ones we know are
|
2009-05-17 08:00:05 +08:00
|
|
|
|
// overridden.
|
|
|
|
|
for (size_t i = 0, e = MethodsSize; i != e; ++i) {
|
|
|
|
|
if (OverriddenMethods.count(Methods[i]))
|
|
|
|
|
Methods[i] = 0;
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-22 09:52:17 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2008-11-05 12:29:56 +08:00
|
|
|
|
|
2009-08-27 08:13:57 +08:00
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
|
2009-03-25 01:23:42 +08:00
|
|
|
|
unsigned DiagID, AbstractDiagSelID SelID,
|
|
|
|
|
const CXXRecordDecl *CurrentRD) {
|
2009-08-27 08:13:57 +08:00
|
|
|
|
if (SelID == -1)
|
|
|
|
|
return RequireNonAbstractType(Loc, T,
|
|
|
|
|
PDiag(DiagID), CurrentRD);
|
|
|
|
|
else
|
|
|
|
|
return RequireNonAbstractType(Loc, T,
|
|
|
|
|
PDiag(DiagID) << SelID, CurrentRD);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-27 08:13:57 +08:00
|
|
|
|
bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
|
|
|
|
|
const PartialDiagnostic &PD,
|
|
|
|
|
const CXXRecordDecl *CurrentRD) {
|
2009-03-23 04:18:17 +08:00
|
|
|
|
if (!getLangOptions().CPlusPlus)
|
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-24 03:10:31 +08:00
|
|
|
|
if (const ArrayType *AT = Context.getAsArrayType(T))
|
2009-08-27 08:13:57 +08:00
|
|
|
|
return RequireNonAbstractType(Loc, AT->getElementType(), PD,
|
2009-03-25 01:23:42 +08:00
|
|
|
|
CurrentRD);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const PointerType *PT = T->getAs<PointerType>()) {
|
2009-03-24 09:46:45 +08:00
|
|
|
|
// Find the innermost pointer type.
|
2009-07-30 05:53:49 +08:00
|
|
|
|
while (const PointerType *T = PT->getPointeeType()->getAs<PointerType>())
|
2009-03-24 09:46:45 +08:00
|
|
|
|
PT = T;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-24 09:46:45 +08:00
|
|
|
|
if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType()))
|
2009-08-27 08:13:57 +08:00
|
|
|
|
return RequireNonAbstractType(Loc, AT->getElementType(), PD, CurrentRD);
|
2009-03-24 09:46:45 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
|
const RecordType *RT = T->getAs<RecordType>();
|
2009-03-23 04:18:17 +08:00
|
|
|
|
if (!RT)
|
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-23 04:18:17 +08:00
|
|
|
|
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
|
|
|
|
|
if (!RD)
|
|
|
|
|
return false;
|
|
|
|
|
|
2009-03-25 01:23:42 +08:00
|
|
|
|
if (CurrentRD && CurrentRD != RD)
|
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-23 04:18:17 +08:00
|
|
|
|
if (!RD->isAbstract())
|
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-27 08:13:57 +08:00
|
|
|
|
Diag(Loc, PD) << RD->getDeclName();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-23 04:18:17 +08:00
|
|
|
|
// Check if we've already emitted the list of pure virtual functions for this
|
|
|
|
|
// class.
|
|
|
|
|
if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD))
|
|
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-23 04:18:17 +08:00
|
|
|
|
PureVirtualMethodCollector Collector(Context, RD);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
|
for (PureVirtualMethodCollector::MethodList::const_iterator I =
|
2009-03-23 04:18:17 +08:00
|
|
|
|
Collector.methods_begin(), E = Collector.methods_end(); I != E; ++I) {
|
|
|
|
|
const CXXMethodDecl *MD = *I;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
|
Diag(MD->getLocation(), diag::note_pure_virtual_function) <<
|
2009-03-23 04:18:17 +08:00
|
|
|
|
MD->getDeclName();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!PureVirtualClassDiagSet)
|
|
|
|
|
PureVirtualClassDiagSet.reset(new RecordDeclSetTy);
|
|
|
|
|
PureVirtualClassDiagSet->insert(RD);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-23 04:18:17 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-24 09:19:16 +08:00
|
|
|
|
namespace {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
class VISIBILITY_HIDDEN AbstractClassUsageDiagnoser
|
2009-03-24 09:19:16 +08:00
|
|
|
|
: public DeclVisitor<AbstractClassUsageDiagnoser, bool> {
|
|
|
|
|
Sema &SemaRef;
|
|
|
|
|
CXXRecordDecl *AbstractClass;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-25 01:23:42 +08:00
|
|
|
|
bool VisitDeclContext(const DeclContext *DC) {
|
2009-03-24 09:19:16 +08:00
|
|
|
|
bool Invalid = false;
|
|
|
|
|
|
2009-06-30 10:36:12 +08:00
|
|
|
|
for (CXXRecordDecl::decl_iterator I = DC->decls_begin(),
|
|
|
|
|
E = DC->decls_end(); I != E; ++I)
|
2009-03-24 09:19:16 +08:00
|
|
|
|
Invalid |= Visit(*I);
|
2009-03-25 01:23:42 +08:00
|
|
|
|
|
2009-03-24 09:19:16 +08:00
|
|
|
|
return Invalid;
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-25 01:23:42 +08:00
|
|
|
|
public:
|
|
|
|
|
AbstractClassUsageDiagnoser(Sema& SemaRef, CXXRecordDecl *ac)
|
|
|
|
|
: SemaRef(SemaRef), AbstractClass(ac) {
|
|
|
|
|
Visit(SemaRef.Context.getTranslationUnitDecl());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool VisitFunctionDecl(const FunctionDecl *FD) {
|
|
|
|
|
if (FD->isThisDeclarationADefinition()) {
|
|
|
|
|
// No need to do the check if we're in a definition, because it requires
|
|
|
|
|
// that the return/param types are complete.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// because that requires
|
2009-03-25 01:23:42 +08:00
|
|
|
|
return VisitDeclContext(FD);
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-24 09:19:16 +08:00
|
|
|
|
// Check the return type.
|
2009-03-25 01:23:42 +08:00
|
|
|
|
QualType RTy = FD->getType()->getAsFunctionType()->getResultType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
bool Invalid =
|
2009-03-25 01:23:42 +08:00
|
|
|
|
SemaRef.RequireNonAbstractType(FD->getLocation(), RTy,
|
2009-03-24 09:19:16 +08:00
|
|
|
|
diag::err_abstract_type_in_decl,
|
2009-03-25 01:23:42 +08:00
|
|
|
|
Sema::AbstractReturnType,
|
|
|
|
|
AbstractClass);
|
2009-03-24 09:19:16 +08:00
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
for (FunctionDecl::param_const_iterator I = FD->param_begin(),
|
2009-03-25 01:23:42 +08:00
|
|
|
|
E = FD->param_end(); I != E; ++I) {
|
2009-03-24 09:19:16 +08:00
|
|
|
|
const ParmVarDecl *VD = *I;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Invalid |=
|
2009-03-24 09:19:16 +08:00
|
|
|
|
SemaRef.RequireNonAbstractType(VD->getLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
|
VD->getOriginalType(),
|
|
|
|
|
diag::err_abstract_type_in_decl,
|
2009-03-25 01:23:42 +08:00
|
|
|
|
Sema::AbstractParamType,
|
|
|
|
|
AbstractClass);
|
2009-03-24 09:19:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Invalid;
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-25 01:23:42 +08:00
|
|
|
|
bool VisitDecl(const Decl* D) {
|
|
|
|
|
if (const DeclContext *DC = dyn_cast<DeclContext>(D))
|
|
|
|
|
return VisitDeclContext(DC);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-25 01:23:42 +08:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2009-03-24 09:19:16 +08:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 18:37:29 +08:00
|
|
|
|
void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
|
2009-03-29 03:18:32 +08:00
|
|
|
|
DeclPtrTy TagDecl,
|
2008-07-01 18:37:29 +08:00
|
|
|
|
SourceLocation LBrac,
|
|
|
|
|
SourceLocation RBrac) {
|
2009-06-23 07:20:33 +08:00
|
|
|
|
if (!TagDecl)
|
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-05-12 03:58:34 +08:00
|
|
|
|
AdjustDeclIfTemplate(TagDecl);
|
2008-07-01 18:37:29 +08:00
|
|
|
|
ActOnFields(S, RLoc, TagDecl,
|
2009-03-29 03:18:32 +08:00
|
|
|
|
(DeclPtrTy*)FieldCollector->getCurFields(),
|
2008-10-03 10:03:53 +08:00
|
|
|
|
FieldCollector->getCurNumFields(), LBrac, RBrac, 0);
|
2009-03-03 12:44:36 +08:00
|
|
|
|
|
2009-03-29 03:18:32 +08:00
|
|
|
|
CXXRecordDecl *RD = cast<CXXRecordDecl>(TagDecl.getAs<Decl>());
|
2009-03-22 09:52:17 +08:00
|
|
|
|
if (!RD->isAbstract()) {
|
|
|
|
|
// Collect all the pure virtual methods and see if this is an abstract
|
|
|
|
|
// class after all.
|
|
|
|
|
PureVirtualMethodCollector Collector(Context, RD);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (!Collector.empty())
|
2009-03-22 09:52:17 +08:00
|
|
|
|
RD->setAbstract(true);
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
|
if (RD->isAbstract())
|
2009-03-25 01:23:42 +08:00
|
|
|
|
AbstractClassUsageDiagnoser(*this, RD);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-05-12 03:58:34 +08:00
|
|
|
|
if (!RD->isDependentType())
|
2009-03-22 09:52:17 +08:00
|
|
|
|
AddImplicitlyDeclaredMembersToClass(RD);
|
2008-07-01 18:37:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-04 01:51:48 +08:00
|
|
|
|
/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
|
|
|
|
|
/// special functions, such as the default constructor, copy
|
|
|
|
|
/// constructor, or destructor, to the given C++ class (C++
|
|
|
|
|
/// [special]p1). This routine can only be executed just before the
|
|
|
|
|
/// definition of the class is complete.
|
|
|
|
|
void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CanQualType ClassType
|
2009-08-05 13:36:45 +08:00
|
|
|
|
= Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
|
2008-11-17 22:58:09 +08:00
|
|
|
|
|
2009-05-28 06:11:52 +08:00
|
|
|
|
// FIXME: Implicit declarations have exception specifications, which are
|
|
|
|
|
// the union of the specifications of the implicitly called functions.
|
|
|
|
|
|
2008-11-04 01:51:48 +08:00
|
|
|
|
if (!ClassDecl->hasUserDeclaredConstructor()) {
|
|
|
|
|
// C++ [class.ctor]p5:
|
|
|
|
|
// A default constructor for a class X is a constructor of class X
|
|
|
|
|
// that can be called without an argument. If there is no
|
|
|
|
|
// user-declared constructor for class X, a default constructor is
|
|
|
|
|
// implicitly declared. An implicitly-declared default constructor
|
|
|
|
|
// is an inline public member of its class.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
DeclarationName Name
|
2008-11-17 22:58:09 +08:00
|
|
|
|
= Context.DeclarationNames.getCXXConstructorName(ClassType);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CXXConstructorDecl *DefaultCon =
|
2008-11-04 01:51:48 +08:00
|
|
|
|
CXXConstructorDecl::Create(Context, ClassDecl,
|
2008-11-17 22:58:09 +08:00
|
|
|
|
ClassDecl->getLocation(), Name,
|
2008-11-04 01:51:48 +08:00
|
|
|
|
Context.getFunctionType(Context.VoidTy,
|
|
|
|
|
0, 0, false, 0),
|
2009-08-19 09:27:57 +08:00
|
|
|
|
/*DInfo=*/0,
|
2008-11-04 01:51:48 +08:00
|
|
|
|
/*isExplicit=*/false,
|
|
|
|
|
/*isInline=*/true,
|
|
|
|
|
/*isImplicitlyDeclared=*/true);
|
|
|
|
|
DefaultCon->setAccess(AS_public);
|
2009-01-08 03:46:03 +08:00
|
|
|
|
DefaultCon->setImplicit();
|
2009-07-23 02:25:24 +08:00
|
|
|
|
DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor());
|
2009-06-30 10:36:12 +08:00
|
|
|
|
ClassDecl->addDecl(DefaultCon);
|
2008-11-04 01:51:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ClassDecl->hasUserDeclaredCopyConstructor()) {
|
|
|
|
|
// C++ [class.copy]p4:
|
|
|
|
|
// If the class definition does not explicitly declare a copy
|
|
|
|
|
// constructor, one is declared implicitly.
|
|
|
|
|
|
|
|
|
|
// C++ [class.copy]p5:
|
|
|
|
|
// The implicitly-declared copy constructor for a class X will
|
|
|
|
|
// have the form
|
|
|
|
|
//
|
|
|
|
|
// X::X(const X&)
|
|
|
|
|
//
|
|
|
|
|
// if
|
|
|
|
|
bool HasConstCopyConstructor = true;
|
|
|
|
|
|
|
|
|
|
// -- each direct or virtual base class B of X has a copy
|
|
|
|
|
// constructor whose first parameter is of type const B& or
|
|
|
|
|
// const volatile B&, and
|
|
|
|
|
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
|
|
|
|
|
HasConstCopyConstructor && Base != ClassDecl->bases_end(); ++Base) {
|
|
|
|
|
const CXXRecordDecl *BaseClassDecl
|
2009-07-30 05:53:49 +08:00
|
|
|
|
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
HasConstCopyConstructor
|
2008-11-04 01:51:48 +08:00
|
|
|
|
= BaseClassDecl->hasConstCopyConstructor(Context);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -- for all the nonstatic data members of X that are of a
|
|
|
|
|
// class type M (or array thereof), each such class type
|
|
|
|
|
// has a copy constructor whose first parameter is of type
|
|
|
|
|
// const M& or const volatile M&.
|
2009-06-30 10:36:12 +08:00
|
|
|
|
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin();
|
|
|
|
|
HasConstCopyConstructor && Field != ClassDecl->field_end();
|
2009-04-10 05:40:53 +08:00
|
|
|
|
++Field) {
|
2008-11-04 01:51:48 +08:00
|
|
|
|
QualType FieldType = (*Field)->getType();
|
|
|
|
|
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
|
|
|
|
|
FieldType = Array->getElementType();
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
const CXXRecordDecl *FieldClassDecl
|
2008-11-04 01:51:48 +08:00
|
|
|
|
= cast<CXXRecordDecl>(FieldClassType->getDecl());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
HasConstCopyConstructor
|
2008-11-04 01:51:48 +08:00
|
|
|
|
= FieldClassDecl->hasConstCopyConstructor(Context);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-01-06 04:52:13 +08:00
|
|
|
|
// Otherwise, the implicitly declared copy constructor will have
|
|
|
|
|
// the form
|
2008-11-04 01:51:48 +08:00
|
|
|
|
//
|
|
|
|
|
// X::X(X&)
|
2009-01-06 04:52:13 +08:00
|
|
|
|
QualType ArgType = ClassType;
|
2008-11-04 01:51:48 +08:00
|
|
|
|
if (HasConstCopyConstructor)
|
|
|
|
|
ArgType = ArgType.withConst();
|
2009-03-17 07:22:08 +08:00
|
|
|
|
ArgType = Context.getLValueReferenceType(ArgType);
|
2008-11-04 01:51:48 +08:00
|
|
|
|
|
2009-01-06 04:52:13 +08:00
|
|
|
|
// An implicitly-declared copy constructor is an inline public
|
|
|
|
|
// member of its class.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
DeclarationName Name
|
2008-11-17 22:58:09 +08:00
|
|
|
|
= Context.DeclarationNames.getCXXConstructorName(ClassType);
|
2008-11-04 01:51:48 +08:00
|
|
|
|
CXXConstructorDecl *CopyConstructor
|
|
|
|
|
= CXXConstructorDecl::Create(Context, ClassDecl,
|
2008-11-17 22:58:09 +08:00
|
|
|
|
ClassDecl->getLocation(), Name,
|
2008-11-04 01:51:48 +08:00
|
|
|
|
Context.getFunctionType(Context.VoidTy,
|
|
|
|
|
&ArgType, 1,
|
|
|
|
|
false, 0),
|
2009-08-19 09:27:57 +08:00
|
|
|
|
/*DInfo=*/0,
|
2008-11-04 01:51:48 +08:00
|
|
|
|
/*isExplicit=*/false,
|
|
|
|
|
/*isInline=*/true,
|
|
|
|
|
/*isImplicitlyDeclared=*/true);
|
|
|
|
|
CopyConstructor->setAccess(AS_public);
|
2009-01-08 03:46:03 +08:00
|
|
|
|
CopyConstructor->setImplicit();
|
2009-07-23 02:25:24 +08:00
|
|
|
|
CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
|
2008-11-04 01:51:48 +08:00
|
|
|
|
|
|
|
|
|
// Add the parameter to the constructor.
|
|
|
|
|
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
|
|
|
|
|
ClassDecl->getLocation(),
|
|
|
|
|
/*IdentifierInfo=*/0,
|
2009-08-19 09:27:57 +08:00
|
|
|
|
ArgType, /*DInfo=*/0,
|
|
|
|
|
VarDecl::None, 0);
|
2009-01-14 08:42:25 +08:00
|
|
|
|
CopyConstructor->setParams(Context, &FromParam, 1);
|
2009-06-30 10:36:12 +08:00
|
|
|
|
ClassDecl->addDecl(CopyConstructor);
|
2008-11-04 01:51:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-01-06 04:52:13 +08:00
|
|
|
|
if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
|
|
|
|
|
// Note: The following rules are largely analoguous to the copy
|
|
|
|
|
// constructor rules. Note that virtual bases are not taken into account
|
|
|
|
|
// for determining the argument type of the operator. Note also that
|
|
|
|
|
// operators taking an object instead of a reference are allowed.
|
|
|
|
|
//
|
|
|
|
|
// C++ [class.copy]p10:
|
|
|
|
|
// If the class definition does not explicitly declare a copy
|
|
|
|
|
// assignment operator, one is declared implicitly.
|
|
|
|
|
// The implicitly-defined copy assignment operator for a class X
|
|
|
|
|
// will have the form
|
|
|
|
|
//
|
|
|
|
|
// X& X::operator=(const X&)
|
|
|
|
|
//
|
|
|
|
|
// if
|
|
|
|
|
bool HasConstCopyAssignment = true;
|
|
|
|
|
|
|
|
|
|
// -- each direct base class B of X has a copy assignment operator
|
|
|
|
|
// whose parameter is of type const B&, const volatile B& or B,
|
|
|
|
|
// and
|
|
|
|
|
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
|
|
|
|
|
HasConstCopyAssignment && Base != ClassDecl->bases_end(); ++Base) {
|
|
|
|
|
const CXXRecordDecl *BaseClassDecl
|
2009-07-30 05:53:49 +08:00
|
|
|
|
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
2009-08-13 07:34:46 +08:00
|
|
|
|
const CXXMethodDecl *MD = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
HasConstCopyAssignment = BaseClassDecl->hasConstCopyAssignment(Context,
|
2009-08-13 07:34:46 +08:00
|
|
|
|
MD);
|
2009-01-06 04:52:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -- for all the nonstatic data members of X that are of a class
|
|
|
|
|
// type M (or array thereof), each such class type has a copy
|
|
|
|
|
// assignment operator whose parameter is of type const M&,
|
|
|
|
|
// const volatile M& or M.
|
2009-06-30 10:36:12 +08:00
|
|
|
|
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin();
|
|
|
|
|
HasConstCopyAssignment && Field != ClassDecl->field_end();
|
2009-04-10 05:40:53 +08:00
|
|
|
|
++Field) {
|
2009-01-06 04:52:13 +08:00
|
|
|
|
QualType FieldType = (*Field)->getType();
|
|
|
|
|
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
|
|
|
|
|
FieldType = Array->getElementType();
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
|
2009-01-06 04:52:13 +08:00
|
|
|
|
const CXXRecordDecl *FieldClassDecl
|
|
|
|
|
= cast<CXXRecordDecl>(FieldClassType->getDecl());
|
2009-08-13 07:34:46 +08:00
|
|
|
|
const CXXMethodDecl *MD = 0;
|
2009-01-06 04:52:13 +08:00
|
|
|
|
HasConstCopyAssignment
|
2009-08-13 07:34:46 +08:00
|
|
|
|
= FieldClassDecl->hasConstCopyAssignment(Context, MD);
|
2009-01-06 04:52:13 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Otherwise, the implicitly declared copy assignment operator will
|
|
|
|
|
// have the form
|
|
|
|
|
//
|
|
|
|
|
// X& X::operator=(X&)
|
|
|
|
|
QualType ArgType = ClassType;
|
2009-03-17 07:22:08 +08:00
|
|
|
|
QualType RetType = Context.getLValueReferenceType(ArgType);
|
2009-01-06 04:52:13 +08:00
|
|
|
|
if (HasConstCopyAssignment)
|
|
|
|
|
ArgType = ArgType.withConst();
|
2009-03-17 07:22:08 +08:00
|
|
|
|
ArgType = Context.getLValueReferenceType(ArgType);
|
2009-01-06 04:52:13 +08:00
|
|
|
|
|
|
|
|
|
// An implicitly-declared copy assignment operator is an inline public
|
|
|
|
|
// member of its class.
|
|
|
|
|
DeclarationName Name =
|
|
|
|
|
Context.DeclarationNames.getCXXOperatorName(OO_Equal);
|
|
|
|
|
CXXMethodDecl *CopyAssignment =
|
|
|
|
|
CXXMethodDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name,
|
|
|
|
|
Context.getFunctionType(RetType, &ArgType, 1,
|
|
|
|
|
false, 0),
|
2009-08-19 09:27:57 +08:00
|
|
|
|
/*DInfo=*/0, /*isStatic=*/false, /*isInline=*/true);
|
2009-01-06 04:52:13 +08:00
|
|
|
|
CopyAssignment->setAccess(AS_public);
|
2009-01-08 03:46:03 +08:00
|
|
|
|
CopyAssignment->setImplicit();
|
2009-07-23 02:25:24 +08:00
|
|
|
|
CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment());
|
2009-08-13 05:14:35 +08:00
|
|
|
|
CopyAssignment->setCopyAssignment(true);
|
2009-01-06 04:52:13 +08:00
|
|
|
|
|
|
|
|
|
// Add the parameter to the operator.
|
|
|
|
|
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
|
|
|
|
|
ClassDecl->getLocation(),
|
|
|
|
|
/*IdentifierInfo=*/0,
|
2009-08-19 09:27:57 +08:00
|
|
|
|
ArgType, /*DInfo=*/0,
|
|
|
|
|
VarDecl::None, 0);
|
2009-01-14 08:42:25 +08:00
|
|
|
|
CopyAssignment->setParams(Context, &FromParam, 1);
|
2009-01-06 04:52:13 +08:00
|
|
|
|
|
|
|
|
|
// Don't call addedAssignmentOperator. There is no way to distinguish an
|
|
|
|
|
// implicit from an explicit assignment operator.
|
2009-06-30 10:36:12 +08:00
|
|
|
|
ClassDecl->addDecl(CopyAssignment);
|
2009-01-06 04:52:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-12-16 05:24:18 +08:00
|
|
|
|
if (!ClassDecl->hasUserDeclaredDestructor()) {
|
2008-11-06 04:51:48 +08:00
|
|
|
|
// C++ [class.dtor]p2:
|
|
|
|
|
// If a class has no user-declared destructor, a destructor is
|
|
|
|
|
// declared implicitly. An implicitly-declared destructor is an
|
|
|
|
|
// inline public member of its class.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
DeclarationName Name
|
2008-11-17 22:58:09 +08:00
|
|
|
|
= Context.DeclarationNames.getCXXDestructorName(ClassType);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CXXDestructorDecl *Destructor
|
2008-11-06 04:51:48 +08:00
|
|
|
|
= CXXDestructorDecl::Create(Context, ClassDecl,
|
2008-11-17 22:58:09 +08:00
|
|
|
|
ClassDecl->getLocation(), Name,
|
2008-11-06 04:51:48 +08:00
|
|
|
|
Context.getFunctionType(Context.VoidTy,
|
|
|
|
|
0, 0, false, 0),
|
|
|
|
|
/*isInline=*/true,
|
|
|
|
|
/*isImplicitlyDeclared=*/true);
|
|
|
|
|
Destructor->setAccess(AS_public);
|
2009-01-08 03:46:03 +08:00
|
|
|
|
Destructor->setImplicit();
|
2009-07-23 02:25:24 +08:00
|
|
|
|
Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
|
2009-06-30 10:36:12 +08:00
|
|
|
|
ClassDecl->addDecl(Destructor);
|
2008-11-06 04:51:48 +08:00
|
|
|
|
}
|
2008-11-04 01:51:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-05-28 07:11:45 +08:00
|
|
|
|
void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) {
|
2009-09-10 08:12:48 +08:00
|
|
|
|
Decl *D = TemplateD.getAs<Decl>();
|
|
|
|
|
if (!D)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
TemplateParameterList *Params = 0;
|
|
|
|
|
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
|
|
|
|
|
Params = Template->getTemplateParameters();
|
|
|
|
|
else if (ClassTemplatePartialSpecializationDecl *PartialSpec
|
|
|
|
|
= dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
|
|
|
|
|
Params = PartialSpec->getTemplateParameters();
|
|
|
|
|
else
|
2009-05-28 07:11:45 +08:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (TemplateParameterList::iterator Param = Params->begin(),
|
|
|
|
|
ParamEnd = Params->end();
|
|
|
|
|
Param != ParamEnd; ++Param) {
|
|
|
|
|
NamedDecl *Named = cast<NamedDecl>(*Param);
|
|
|
|
|
if (Named->getDeclName()) {
|
|
|
|
|
S->AddDecl(DeclPtrTy::make(Named));
|
|
|
|
|
IdResolver.AddDecl(Named);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-17 05:30:33 +08:00
|
|
|
|
/// ActOnStartDelayedCXXMethodDeclaration - We have completed
|
|
|
|
|
/// parsing a top-level (non-nested) C++ class, and we are now
|
|
|
|
|
/// parsing those parts of the given Method declaration that could
|
|
|
|
|
/// not be parsed earlier (C++ [class.mem]p2), such as default
|
|
|
|
|
/// arguments. This action should enter the scope of the given
|
|
|
|
|
/// Method declaration as if we had just parsed the qualified method
|
|
|
|
|
/// name. However, it should not bring the parameters into scope;
|
|
|
|
|
/// that will be performed by ActOnDelayedCXXMethodParameter.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
|
2009-06-23 07:20:33 +08:00
|
|
|
|
if (!MethodD)
|
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-24 19:57:43 +08:00
|
|
|
|
AdjustDeclIfTemplate(MethodD);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2008-12-17 05:30:33 +08:00
|
|
|
|
CXXScopeSpec SS;
|
2009-03-29 03:18:32 +08:00
|
|
|
|
FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
QualType ClassTy
|
2009-03-27 07:50:42 +08:00
|
|
|
|
= Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
|
|
|
|
|
SS.setScopeRep(
|
|
|
|
|
NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr()));
|
2008-12-17 05:30:33 +08:00
|
|
|
|
ActOnCXXEnterDeclaratorScope(S, SS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// ActOnDelayedCXXMethodParameter - We've already started a delayed
|
|
|
|
|
/// C++ method declaration. We're (re-)introducing the given
|
|
|
|
|
/// function parameter into scope for use in parsing later parts of
|
|
|
|
|
/// the method declaration. For example, we could see an
|
|
|
|
|
/// ActOnParamDefaultArgument event for this parameter.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) {
|
2009-06-23 07:20:33 +08:00
|
|
|
|
if (!ParamD)
|
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-29 03:18:32 +08:00
|
|
|
|
ParmVarDecl *Param = cast<ParmVarDecl>(ParamD.getAs<Decl>());
|
2008-12-24 08:01:03 +08:00
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
2009-03-29 03:18:32 +08:00
|
|
|
|
S->AddDecl(DeclPtrTy::make(Param));
|
2008-12-17 05:30:33 +08:00
|
|
|
|
if (Param->getDeclName())
|
|
|
|
|
IdResolver.AddDecl(Param);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// ActOnFinishDelayedCXXMethodDeclaration - We have finished
|
|
|
|
|
/// processing the delayed method declaration for Method. The method
|
|
|
|
|
/// declaration is now considered finished. There may be a separate
|
|
|
|
|
/// ActOnStartOfFunctionDef action later (not necessarily
|
|
|
|
|
/// immediately!) for this method, if it was also defined inside the
|
|
|
|
|
/// class body.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
|
2009-06-23 07:20:33 +08:00
|
|
|
|
if (!MethodD)
|
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-24 19:57:43 +08:00
|
|
|
|
AdjustDeclIfTemplate(MethodD);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-29 03:18:32 +08:00
|
|
|
|
FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
|
2008-12-17 05:30:33 +08:00
|
|
|
|
CXXScopeSpec SS;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
QualType ClassTy
|
2009-03-27 07:50:42 +08:00
|
|
|
|
= Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
|
|
|
|
|
SS.setScopeRep(
|
|
|
|
|
NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr()));
|
2008-12-17 05:30:33 +08:00
|
|
|
|
ActOnCXXExitDeclaratorScope(S, SS);
|
|
|
|
|
|
|
|
|
|
// Now that we have our default arguments, check the constructor
|
|
|
|
|
// again. It could produce additional diagnostics or affect whether
|
|
|
|
|
// the class has implicitly-declared destructors, among other
|
|
|
|
|
// things.
|
2009-04-25 16:35:12 +08:00
|
|
|
|
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Method))
|
|
|
|
|
CheckConstructor(Constructor);
|
2008-12-17 05:30:33 +08:00
|
|
|
|
|
|
|
|
|
// Check the default arguments, which we may have added.
|
|
|
|
|
if (!Method->isInvalidDecl())
|
|
|
|
|
CheckCXXDefaultArguments(Method);
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-06 04:51:48 +08:00
|
|
|
|
/// CheckConstructorDeclarator - Called by ActOnDeclarator to check
|
2008-12-17 05:30:33 +08:00
|
|
|
|
/// the well-formedness of the constructor declarator @p D with type @p
|
2008-11-06 04:51:48 +08:00
|
|
|
|
/// R. If there are any errors in the declarator, this routine will
|
2009-04-25 16:28:21 +08:00
|
|
|
|
/// emit diagnostics and set the invalid bit to true. In any case, the type
|
|
|
|
|
/// will be updated to reflect a well-formed type for the constructor and
|
|
|
|
|
/// returned.
|
|
|
|
|
QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
|
|
|
|
|
FunctionDecl::StorageClass &SC) {
|
2008-11-06 04:51:48 +08:00
|
|
|
|
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
|
|
|
|
|
|
|
|
|
|
// C++ [class.ctor]p3:
|
|
|
|
|
// A constructor shall not be virtual (10.3) or static (9.4). A
|
|
|
|
|
// constructor can be invoked for a const, volatile or const
|
|
|
|
|
// volatile object. A constructor shall not be declared const,
|
|
|
|
|
// volatile, or const volatile (9.3.2).
|
|
|
|
|
if (isVirtual) {
|
2009-04-25 16:28:21 +08:00
|
|
|
|
if (!D.isInvalidType())
|
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
|
|
|
|
|
<< "virtual" << SourceRange(D.getDeclSpec().getVirtualSpecLoc())
|
|
|
|
|
<< SourceRange(D.getIdentifierLoc());
|
|
|
|
|
D.setInvalidType();
|
2008-11-06 04:51:48 +08:00
|
|
|
|
}
|
|
|
|
|
if (SC == FunctionDecl::Static) {
|
2009-04-25 16:28:21 +08:00
|
|
|
|
if (!D.isInvalidType())
|
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
|
|
|
|
|
<< "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
|
|
|
|
|
<< SourceRange(D.getIdentifierLoc());
|
|
|
|
|
D.setInvalidType();
|
2008-11-06 04:51:48 +08:00
|
|
|
|
SC = FunctionDecl::None;
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-04-25 16:28:21 +08:00
|
|
|
|
DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
|
|
|
|
|
if (FTI.TypeQuals != 0) {
|
2008-11-06 04:51:48 +08:00
|
|
|
|
if (FTI.TypeQuals & QualType::Const)
|
2008-11-19 13:08:23 +08:00
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
|
|
|
|
|
<< "const" << SourceRange(D.getIdentifierLoc());
|
2008-11-06 04:51:48 +08:00
|
|
|
|
if (FTI.TypeQuals & QualType::Volatile)
|
2008-11-19 13:08:23 +08:00
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
|
|
|
|
|
<< "volatile" << SourceRange(D.getIdentifierLoc());
|
2008-11-06 04:51:48 +08:00
|
|
|
|
if (FTI.TypeQuals & QualType::Restrict)
|
2008-11-19 13:08:23 +08:00
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
|
|
|
|
|
<< "restrict" << SourceRange(D.getIdentifierLoc());
|
2008-11-06 04:51:48 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2008-11-06 04:51:48 +08:00
|
|
|
|
// Rebuild the function type "R" without any type qualifiers (in
|
|
|
|
|
// case any of the errors above fired) and with "void" as the
|
|
|
|
|
// return type, since constructors don't have return types. We
|
|
|
|
|
// *always* have to do this, because GetTypeForDeclarator will
|
|
|
|
|
// put in a result type of "int" when none was specified.
|
2009-02-27 07:50:07 +08:00
|
|
|
|
const FunctionProtoType *Proto = R->getAsFunctionProtoType();
|
2009-04-25 16:28:21 +08:00
|
|
|
|
return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(),
|
|
|
|
|
Proto->getNumArgs(),
|
|
|
|
|
Proto->isVariadic(), 0);
|
2008-11-06 04:51:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-12-17 05:30:33 +08:00
|
|
|
|
/// CheckConstructor - Checks a fully-formed constructor for
|
|
|
|
|
/// well-formedness, issuing any diagnostics required. Returns true if
|
|
|
|
|
/// the constructor declarator is invalid.
|
2009-04-25 16:35:12 +08:00
|
|
|
|
void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CXXRecordDecl *ClassDecl
|
2009-03-27 12:38:56 +08:00
|
|
|
|
= dyn_cast<CXXRecordDecl>(Constructor->getDeclContext());
|
|
|
|
|
if (!ClassDecl)
|
2009-04-25 16:35:12 +08:00
|
|
|
|
return Constructor->setInvalidDecl();
|
2008-12-17 05:30:33 +08:00
|
|
|
|
|
|
|
|
|
// C++ [class.copy]p3:
|
|
|
|
|
// A declaration of a constructor for a class X is ill-formed if
|
|
|
|
|
// its first parameter is of type (optionally cv-qualified) X and
|
|
|
|
|
// either there are no other parameters or else all other
|
|
|
|
|
// parameters have default arguments.
|
2009-03-27 12:38:56 +08:00
|
|
|
|
if (!Constructor->isInvalidDecl() &&
|
2009-09-09 23:08:12 +08:00
|
|
|
|
((Constructor->getNumParams() == 1) ||
|
|
|
|
|
(Constructor->getNumParams() > 1 &&
|
2009-06-06 12:14:07 +08:00
|
|
|
|
Constructor->getParamDecl(1)->hasDefaultArg()))) {
|
2008-12-17 05:30:33 +08:00
|
|
|
|
QualType ParamType = Constructor->getParamDecl(0)->getType();
|
|
|
|
|
QualType ClassTy = Context.getTagDeclType(ClassDecl);
|
|
|
|
|
if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
|
2009-04-02 07:51:29 +08:00
|
|
|
|
SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation();
|
|
|
|
|
Diag(ParamLoc, diag::err_constructor_byvalue_arg)
|
2009-04-02 09:08:08 +08:00
|
|
|
|
<< CodeModificationHint::CreateInsertion(ParamLoc, " const &");
|
2009-04-25 16:35:12 +08:00
|
|
|
|
Constructor->setInvalidDecl();
|
2008-12-17 05:30:33 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2008-12-17 05:30:33 +08:00
|
|
|
|
// Notify the class that we've added a constructor.
|
|
|
|
|
ClassDecl->addedConstructor(Context, Constructor);
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
static inline bool
|
2009-05-01 07:18:11 +08:00
|
|
|
|
FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) {
|
|
|
|
|
return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
|
|
|
|
|
FTI.ArgInfo[0].Param &&
|
|
|
|
|
FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType()->isVoidType());
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-06 04:51:48 +08:00
|
|
|
|
/// CheckDestructorDeclarator - Called by ActOnDeclarator to check
|
|
|
|
|
/// the well-formednes of the destructor declarator @p D with type @p
|
|
|
|
|
/// R. If there are any errors in the declarator, this routine will
|
2009-04-25 16:28:21 +08:00
|
|
|
|
/// emit diagnostics and set the declarator to invalid. Even if this happens,
|
|
|
|
|
/// will be updated to reflect a well-formed type for the destructor and
|
|
|
|
|
/// returned.
|
|
|
|
|
QualType Sema::CheckDestructorDeclarator(Declarator &D,
|
|
|
|
|
FunctionDecl::StorageClass& SC) {
|
2008-11-06 04:51:48 +08:00
|
|
|
|
// C++ [class.dtor]p1:
|
|
|
|
|
// [...] A typedef-name that names a class is a class-name
|
|
|
|
|
// (7.1.3); however, a typedef-name that names a class shall not
|
|
|
|
|
// be used as the identifier in the declarator for a destructor
|
|
|
|
|
// declaration.
|
2009-08-19 09:28:28 +08:00
|
|
|
|
QualType DeclaratorType = GetTypeFromParser(D.getDeclaratorIdType());
|
2009-04-25 16:28:21 +08:00
|
|
|
|
if (isa<TypedefType>(DeclaratorType)) {
|
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
|
2009-02-09 23:09:02 +08:00
|
|
|
|
<< DeclaratorType;
|
2009-04-25 16:28:21 +08:00
|
|
|
|
D.setInvalidType();
|
2008-11-06 04:51:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// C++ [class.dtor]p2:
|
|
|
|
|
// A destructor is used to destroy objects of its class type. A
|
|
|
|
|
// destructor takes no parameters, and no return type can be
|
|
|
|
|
// specified for it (not even void). The address of a destructor
|
|
|
|
|
// shall not be taken. A destructor shall not be static. A
|
|
|
|
|
// destructor can be invoked for a const, volatile or const
|
|
|
|
|
// volatile object. A destructor shall not be declared const,
|
|
|
|
|
// volatile or const volatile (9.3.2).
|
|
|
|
|
if (SC == FunctionDecl::Static) {
|
2009-04-25 16:28:21 +08:00
|
|
|
|
if (!D.isInvalidType())
|
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be)
|
|
|
|
|
<< "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
|
|
|
|
|
<< SourceRange(D.getIdentifierLoc());
|
2008-11-06 04:51:48 +08:00
|
|
|
|
SC = FunctionDecl::None;
|
2009-04-25 16:28:21 +08:00
|
|
|
|
D.setInvalidType();
|
2008-11-06 04:51:48 +08:00
|
|
|
|
}
|
2009-04-25 16:28:21 +08:00
|
|
|
|
if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
|
2008-11-06 04:51:48 +08:00
|
|
|
|
// Destructors don't have return types, but the parser will
|
|
|
|
|
// happily parse something like:
|
|
|
|
|
//
|
|
|
|
|
// class X {
|
|
|
|
|
// float ~X();
|
|
|
|
|
// };
|
|
|
|
|
//
|
|
|
|
|
// The return type will be eliminated later.
|
2008-11-19 13:08:23 +08:00
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_destructor_return_type)
|
|
|
|
|
<< SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
|
|
|
|
|
<< SourceRange(D.getIdentifierLoc());
|
2008-11-06 04:51:48 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-04-25 16:28:21 +08:00
|
|
|
|
DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
|
|
|
|
|
if (FTI.TypeQuals != 0 && !D.isInvalidType()) {
|
2008-11-06 04:51:48 +08:00
|
|
|
|
if (FTI.TypeQuals & QualType::Const)
|
2008-11-19 13:08:23 +08:00
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
|
|
|
|
|
<< "const" << SourceRange(D.getIdentifierLoc());
|
2008-11-06 04:51:48 +08:00
|
|
|
|
if (FTI.TypeQuals & QualType::Volatile)
|
2008-11-19 13:08:23 +08:00
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
|
|
|
|
|
<< "volatile" << SourceRange(D.getIdentifierLoc());
|
2008-11-06 04:51:48 +08:00
|
|
|
|
if (FTI.TypeQuals & QualType::Restrict)
|
2008-11-19 13:08:23 +08:00
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
|
|
|
|
|
<< "restrict" << SourceRange(D.getIdentifierLoc());
|
2009-04-25 16:28:21 +08:00
|
|
|
|
D.setInvalidType();
|
2008-11-06 04:51:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make sure we don't have any parameters.
|
2009-05-01 07:18:11 +08:00
|
|
|
|
if (FTI.NumArgs > 0 && !FTIHasSingleVoidArgument(FTI)) {
|
2008-11-06 04:51:48 +08:00
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_destructor_with_params);
|
|
|
|
|
|
|
|
|
|
// Delete the parameters.
|
2009-04-25 16:28:21 +08:00
|
|
|
|
FTI.freeArgs();
|
|
|
|
|
D.setInvalidType();
|
2008-11-06 04:51:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// Make sure the destructor isn't variadic.
|
2009-04-25 16:28:21 +08:00
|
|
|
|
if (FTI.isVariadic) {
|
2008-11-06 04:51:48 +08:00
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_destructor_variadic);
|
2009-04-25 16:28:21 +08:00
|
|
|
|
D.setInvalidType();
|
|
|
|
|
}
|
2008-11-06 04:51:48 +08:00
|
|
|
|
|
|
|
|
|
// Rebuild the function type "R" without any type qualifiers or
|
|
|
|
|
// parameters (in case any of the errors above fired) and with
|
|
|
|
|
// "void" as the return type, since destructors don't have return
|
|
|
|
|
// types. We *always* have to do this, because GetTypeForDeclarator
|
|
|
|
|
// will put in a result type of "int" when none was specified.
|
2009-04-25 16:28:21 +08:00
|
|
|
|
return Context.getFunctionType(Context.VoidTy, 0, 0, false, 0);
|
2008-11-06 04:51:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-08 04:08:42 +08:00
|
|
|
|
/// CheckConversionDeclarator - Called by ActOnDeclarator to check the
|
|
|
|
|
/// well-formednes of the conversion function declarator @p D with
|
|
|
|
|
/// type @p R. If there are any errors in the declarator, this routine
|
|
|
|
|
/// will emit diagnostics and return true. Otherwise, it will return
|
|
|
|
|
/// false. Either way, the type @p R will be updated to reflect a
|
|
|
|
|
/// well-formed type for the conversion operator.
|
2009-04-25 16:35:12 +08:00
|
|
|
|
void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
|
2008-11-08 04:08:42 +08:00
|
|
|
|
FunctionDecl::StorageClass& SC) {
|
|
|
|
|
// C++ [class.conv.fct]p1:
|
|
|
|
|
// Neither parameter types nor return type can be specified. The
|
2009-08-06 03:21:58 +08:00
|
|
|
|
// type of a conversion function (8.3.5) is "function taking no
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// parameter returning conversion-type-id."
|
2008-11-08 04:08:42 +08:00
|
|
|
|
if (SC == FunctionDecl::Static) {
|
2009-04-25 16:35:12 +08:00
|
|
|
|
if (!D.isInvalidType())
|
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member)
|
|
|
|
|
<< "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
|
|
|
|
|
<< SourceRange(D.getIdentifierLoc());
|
|
|
|
|
D.setInvalidType();
|
2008-11-08 04:08:42 +08:00
|
|
|
|
SC = FunctionDecl::None;
|
|
|
|
|
}
|
2009-04-25 16:35:12 +08:00
|
|
|
|
if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
|
2008-11-08 04:08:42 +08:00
|
|
|
|
// Conversion functions don't have return types, but the parser will
|
|
|
|
|
// happily parse something like:
|
|
|
|
|
//
|
|
|
|
|
// class X {
|
|
|
|
|
// float operator bool();
|
|
|
|
|
// };
|
|
|
|
|
//
|
|
|
|
|
// The return type will be changed later anyway.
|
2008-11-19 13:08:23 +08:00
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type)
|
|
|
|
|
<< SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
|
|
|
|
|
<< SourceRange(D.getIdentifierLoc());
|
2008-11-08 04:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make sure we don't have any parameters.
|
2009-02-27 07:50:07 +08:00
|
|
|
|
if (R->getAsFunctionProtoType()->getNumArgs() > 0) {
|
2008-11-08 04:08:42 +08:00
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params);
|
|
|
|
|
|
|
|
|
|
// Delete the parameters.
|
2009-01-21 05:06:38 +08:00
|
|
|
|
D.getTypeObject(0).Fun.freeArgs();
|
2009-04-25 16:35:12 +08:00
|
|
|
|
D.setInvalidType();
|
2008-11-08 04:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// Make sure the conversion function isn't variadic.
|
2009-04-25 16:35:12 +08:00
|
|
|
|
if (R->getAsFunctionProtoType()->isVariadic() && !D.isInvalidType()) {
|
2008-11-08 04:08:42 +08:00
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic);
|
2009-04-25 16:35:12 +08:00
|
|
|
|
D.setInvalidType();
|
|
|
|
|
}
|
2008-11-08 04:08:42 +08:00
|
|
|
|
|
|
|
|
|
// C++ [class.conv.fct]p4:
|
|
|
|
|
// The conversion-type-id shall not represent a function type nor
|
|
|
|
|
// an array type.
|
2009-08-19 09:28:28 +08:00
|
|
|
|
QualType ConvType = GetTypeFromParser(D.getDeclaratorIdType());
|
2008-11-08 04:08:42 +08:00
|
|
|
|
if (ConvType->isArrayType()) {
|
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array);
|
|
|
|
|
ConvType = Context.getPointerType(ConvType);
|
2009-04-25 16:35:12 +08:00
|
|
|
|
D.setInvalidType();
|
2008-11-08 04:08:42 +08:00
|
|
|
|
} else if (ConvType->isFunctionType()) {
|
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_conv_function_to_function);
|
|
|
|
|
ConvType = Context.getPointerType(ConvType);
|
2009-04-25 16:35:12 +08:00
|
|
|
|
D.setInvalidType();
|
2008-11-08 04:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Rebuild the function type "R" without any parameters (in case any
|
|
|
|
|
// of the errors above fired) and with the conversion type as the
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// return type.
|
|
|
|
|
R = Context.getFunctionType(ConvType, 0, 0, false,
|
2009-02-27 07:50:07 +08:00
|
|
|
|
R->getAsFunctionProtoType()->getTypeQuals());
|
2008-11-08 04:08:42 +08:00
|
|
|
|
|
2009-01-14 23:45:31 +08:00
|
|
|
|
// C++0x explicit conversion operators.
|
|
|
|
|
if (D.getDeclSpec().isExplicitSpecified() && !getLangOptions().CPlusPlus0x)
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(D.getDeclSpec().getExplicitSpecLoc(),
|
2009-01-14 23:45:31 +08:00
|
|
|
|
diag::warn_explicit_conversion_functions)
|
|
|
|
|
<< SourceRange(D.getDeclSpec().getExplicitSpecLoc());
|
2008-11-08 04:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// ActOnConversionDeclarator - Called by ActOnDeclarator to complete
|
|
|
|
|
/// the declaration of the given C++ conversion function. This routine
|
|
|
|
|
/// is responsible for recording the conversion function in the C++
|
|
|
|
|
/// class, if possible.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
|
2008-11-08 04:08:42 +08:00
|
|
|
|
assert(Conversion && "Expected to receive a conversion function declaration");
|
|
|
|
|
|
2008-12-12 16:25:50 +08:00
|
|
|
|
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Conversion->getDeclContext());
|
2008-11-08 04:08:42 +08:00
|
|
|
|
|
|
|
|
|
// Make sure we aren't redeclaring the conversion function.
|
|
|
|
|
QualType ConvType = Context.getCanonicalType(Conversion->getConversionType());
|
|
|
|
|
|
|
|
|
|
// C++ [class.conv.fct]p1:
|
|
|
|
|
// [...] A conversion function is never used to convert a
|
|
|
|
|
// (possibly cv-qualified) object to the (possibly cv-qualified)
|
|
|
|
|
// same object type (or a reference to it), to a (possibly
|
|
|
|
|
// cv-qualified) base class of that type (or a reference to it),
|
|
|
|
|
// or to (possibly cv-qualified) void.
|
2009-05-16 15:39:55 +08:00
|
|
|
|
// FIXME: Suppress this warning if the conversion function ends up being a
|
|
|
|
|
// virtual function that overrides a virtual function in a base class.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
QualType ClassType
|
2008-11-08 04:08:42 +08:00
|
|
|
|
= Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const ReferenceType *ConvTypeRef = ConvType->getAs<ReferenceType>())
|
2008-11-08 04:08:42 +08:00
|
|
|
|
ConvType = ConvTypeRef->getPointeeType();
|
|
|
|
|
if (ConvType->isRecordType()) {
|
|
|
|
|
ConvType = Context.getCanonicalType(ConvType).getUnqualifiedType();
|
|
|
|
|
if (ConvType == ClassType)
|
2008-11-20 14:13:02 +08:00
|
|
|
|
Diag(Conversion->getLocation(), diag::warn_conv_to_self_not_used)
|
2008-11-24 14:25:27 +08:00
|
|
|
|
<< ClassType;
|
2008-11-08 04:08:42 +08:00
|
|
|
|
else if (IsDerivedFrom(ClassType, ConvType))
|
2008-11-20 14:13:02 +08:00
|
|
|
|
Diag(Conversion->getLocation(), diag::warn_conv_to_base_not_used)
|
2008-11-24 14:25:27 +08:00
|
|
|
|
<< ClassType << ConvType;
|
2008-11-08 04:08:42 +08:00
|
|
|
|
} else if (ConvType->isVoidType()) {
|
2008-11-20 14:13:02 +08:00
|
|
|
|
Diag(Conversion->getLocation(), diag::warn_conv_to_void_not_used)
|
2008-11-24 14:25:27 +08:00
|
|
|
|
<< ClassType << ConvType;
|
2008-11-08 04:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-12-26 23:00:45 +08:00
|
|
|
|
if (Conversion->getPreviousDeclaration()) {
|
2009-08-22 07:19:43 +08:00
|
|
|
|
const NamedDecl *ExpectedPrevDecl = Conversion->getPreviousDeclaration();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (FunctionTemplateDecl *ConversionTemplate
|
2009-08-22 07:19:43 +08:00
|
|
|
|
= Conversion->getDescribedFunctionTemplate())
|
|
|
|
|
ExpectedPrevDecl = ConversionTemplate->getPreviousDeclaration();
|
2008-12-26 23:00:45 +08:00
|
|
|
|
OverloadedFunctionDecl *Conversions = ClassDecl->getConversionFunctions();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
for (OverloadedFunctionDecl::function_iterator
|
2008-12-26 23:00:45 +08:00
|
|
|
|
Conv = Conversions->function_begin(),
|
|
|
|
|
ConvEnd = Conversions->function_end();
|
|
|
|
|
Conv != ConvEnd; ++Conv) {
|
2009-08-22 07:19:43 +08:00
|
|
|
|
if (*Conv == ExpectedPrevDecl) {
|
2008-12-26 23:00:45 +08:00
|
|
|
|
*Conv = Conversion;
|
2009-03-29 03:18:32 +08:00
|
|
|
|
return DeclPtrTy::make(Conversion);
|
2008-12-26 23:00:45 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
assert(Conversion->isInvalidDecl() && "Conversion should not get here.");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
} else if (FunctionTemplateDecl *ConversionTemplate
|
2009-08-22 07:19:43 +08:00
|
|
|
|
= Conversion->getDescribedFunctionTemplate())
|
2009-09-13 03:02:34 +08:00
|
|
|
|
ClassDecl->addConversionFunction(ConversionTemplate);
|
2009-08-22 07:19:43 +08:00
|
|
|
|
else if (!Conversion->getPrimaryTemplate()) // ignore specializations
|
2009-09-13 03:02:34 +08:00
|
|
|
|
ClassDecl->addConversionFunction(Conversion);
|
2008-11-08 04:08:42 +08:00
|
|
|
|
|
2009-03-29 03:18:32 +08:00
|
|
|
|
return DeclPtrTy::make(Conversion);
|
2008-11-08 04:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-04-27 21:50:30 +08:00
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
// Namespace Handling
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
/// ActOnStartNamespaceDef - This is called at the start of a namespace
|
|
|
|
|
/// definition.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
|
|
|
|
|
SourceLocation IdentLoc,
|
|
|
|
|
IdentifierInfo *II,
|
|
|
|
|
SourceLocation LBrace) {
|
2008-04-27 21:50:30 +08:00
|
|
|
|
NamespaceDecl *Namespc =
|
|
|
|
|
NamespaceDecl::Create(Context, CurContext, IdentLoc, II);
|
|
|
|
|
Namespc->setLBracLoc(LBrace);
|
|
|
|
|
|
|
|
|
|
Scope *DeclRegionScope = NamespcScope->getParent();
|
|
|
|
|
|
|
|
|
|
if (II) {
|
|
|
|
|
// C++ [namespace.def]p2:
|
|
|
|
|
// The identifier in an original-namespace-definition shall not have been
|
|
|
|
|
// previously defined in the declarative region in which the
|
|
|
|
|
// original-namespace-definition appears. The identifier in an
|
|
|
|
|
// original-namespace-definition is the name of the namespace. Subsequently
|
|
|
|
|
// in that declarative region, it is treated as an original-namespace-name.
|
|
|
|
|
|
2009-02-05 01:27:36 +08:00
|
|
|
|
NamedDecl *PrevDecl = LookupName(DeclRegionScope, II, LookupOrdinaryName,
|
|
|
|
|
true);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2008-12-12 00:49:14 +08:00
|
|
|
|
if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) {
|
|
|
|
|
// This is an extended namespace definition.
|
|
|
|
|
// Attach this namespace decl to the chain of extended namespace
|
|
|
|
|
// definitions.
|
|
|
|
|
OrigNS->setNextNamespace(Namespc);
|
|
|
|
|
Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace());
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// Remove the previous declaration from the scope.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
if (DeclRegionScope->isDeclScope(DeclPtrTy::make(OrigNS))) {
|
2008-12-12 04:41:00 +08:00
|
|
|
|
IdResolver.RemoveDecl(OrigNS);
|
2009-03-29 03:18:32 +08:00
|
|
|
|
DeclRegionScope->RemoveDecl(DeclPtrTy::make(OrigNS));
|
2008-04-27 21:50:30 +08:00
|
|
|
|
}
|
2008-12-12 00:49:14 +08:00
|
|
|
|
} else if (PrevDecl) {
|
|
|
|
|
// This is an invalid name redefinition.
|
|
|
|
|
Diag(Namespc->getLocation(), diag::err_redefinition_different_kind)
|
|
|
|
|
<< Namespc->getDeclName();
|
|
|
|
|
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
|
|
|
|
Namespc->setInvalidDecl();
|
|
|
|
|
// Continue on to push Namespc as current DeclContext and return it.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
}
|
2008-12-12 00:49:14 +08:00
|
|
|
|
|
|
|
|
|
PushOnScopeChains(Namespc, DeclRegionScope);
|
|
|
|
|
} else {
|
2008-04-27 21:50:30 +08:00
|
|
|
|
// FIXME: Handle anonymous namespaces
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Although we could have an invalid decl (i.e. the namespace name is a
|
|
|
|
|
// redefinition), push it as current DeclContext and try to continue parsing.
|
2009-05-16 15:39:55 +08:00
|
|
|
|
// FIXME: We should be able to push Namespc here, so that the each DeclContext
|
|
|
|
|
// for the namespace has the declarations that showed up in that particular
|
|
|
|
|
// namespace definition.
|
2008-12-12 00:49:14 +08:00
|
|
|
|
PushDeclContext(NamespcScope, Namespc);
|
2009-03-29 03:18:32 +08:00
|
|
|
|
return DeclPtrTy::make(Namespc);
|
2008-04-27 21:50:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// ActOnFinishNamespaceDef - This callback is called after a namespace is
|
|
|
|
|
/// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
void Sema::ActOnFinishNamespaceDef(DeclPtrTy D, SourceLocation RBrace) {
|
|
|
|
|
Decl *Dcl = D.getAs<Decl>();
|
2008-04-27 21:50:30 +08:00
|
|
|
|
NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl);
|
|
|
|
|
assert(Namespc && "Invalid parameter, expected NamespaceDecl");
|
|
|
|
|
Namespc->setRBracLoc(RBrace);
|
|
|
|
|
PopDeclContext();
|
|
|
|
|
}
|
2008-10-07 01:10:33 +08:00
|
|
|
|
|
2009-03-29 03:18:32 +08:00
|
|
|
|
Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S,
|
|
|
|
|
SourceLocation UsingLoc,
|
|
|
|
|
SourceLocation NamespcLoc,
|
|
|
|
|
const CXXScopeSpec &SS,
|
|
|
|
|
SourceLocation IdentLoc,
|
|
|
|
|
IdentifierInfo *NamespcName,
|
|
|
|
|
AttributeList *AttrList) {
|
2008-12-30 11:27:21 +08:00
|
|
|
|
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
|
|
|
|
|
assert(NamespcName && "Invalid NamespcName.");
|
|
|
|
|
assert(IdentLoc.isValid() && "Invalid NamespceName location.");
|
2009-02-04 03:21:40 +08:00
|
|
|
|
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
|
2008-12-30 11:27:21 +08:00
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
UsingDirectiveDecl *UDir = 0;
|
2009-01-15 06:20:51 +08:00
|
|
|
|
|
2008-12-30 11:27:21 +08:00
|
|
|
|
// Lookup namespace name.
|
2009-02-04 03:21:40 +08:00
|
|
|
|
LookupResult R = LookupParsedName(S, &SS, NamespcName,
|
|
|
|
|
LookupNamespaceName, false);
|
|
|
|
|
if (R.isAmbiguous()) {
|
|
|
|
|
DiagnoseAmbiguousLookup(R, NamespcName, IdentLoc);
|
2009-03-29 03:18:32 +08:00
|
|
|
|
return DeclPtrTy();
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
2009-02-05 01:27:36 +08:00
|
|
|
|
if (NamedDecl *NS = R) {
|
2008-12-30 11:27:21 +08:00
|
|
|
|
assert(isa<NamespaceDecl>(NS) && "expected namespace decl");
|
2009-02-04 03:21:40 +08:00
|
|
|
|
// C++ [namespace.udir]p1:
|
|
|
|
|
// A using-directive specifies that the names in the nominated
|
|
|
|
|
// namespace can be used in the scope in which the
|
|
|
|
|
// using-directive appears after the using-directive. During
|
|
|
|
|
// unqualified name lookup (3.4.1), the names appear as if they
|
|
|
|
|
// were declared in the nearest enclosing namespace which
|
|
|
|
|
// contains both the using-directive and the nominated
|
2009-08-06 03:21:58 +08:00
|
|
|
|
// namespace. [Note: in this context, "contains" means "contains
|
|
|
|
|
// directly or indirectly". ]
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
|
|
|
|
// Find enclosing context containing both using-directive and
|
|
|
|
|
// nominated namespace.
|
|
|
|
|
DeclContext *CommonAncestor = cast<DeclContext>(NS);
|
|
|
|
|
while (CommonAncestor && !CommonAncestor->Encloses(CurContext))
|
|
|
|
|
CommonAncestor = CommonAncestor->getParent();
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
UDir = UsingDirectiveDecl::Create(Context,
|
2009-05-30 14:31:56 +08:00
|
|
|
|
CurContext, UsingLoc,
|
2009-09-09 23:08:12 +08:00
|
|
|
|
NamespcLoc,
|
2009-05-30 14:31:56 +08:00
|
|
|
|
SS.getRange(),
|
|
|
|
|
(NestedNameSpecifier *)SS.getScopeRep(),
|
|
|
|
|
IdentLoc,
|
2009-02-04 03:21:40 +08:00
|
|
|
|
cast<NamespaceDecl>(NS),
|
|
|
|
|
CommonAncestor);
|
|
|
|
|
PushUsingDirective(S, UDir);
|
2008-12-30 11:27:21 +08:00
|
|
|
|
} else {
|
2009-01-06 15:24:29 +08:00
|
|
|
|
Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
|
2008-12-30 11:27:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
// FIXME: We ignore attributes for now.
|
2008-12-30 11:27:21 +08:00
|
|
|
|
delete AttrList;
|
2009-03-29 03:18:32 +08:00
|
|
|
|
return DeclPtrTy::make(UDir);
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
|
|
|
|
|
// If scope has associated entity, then using directive is at namespace
|
|
|
|
|
// or translation unit scope. We add UsingDirectiveDecls, into
|
|
|
|
|
// it's lookup structure.
|
|
|
|
|
if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()))
|
2009-06-30 10:36:12 +08:00
|
|
|
|
Ctx->addDecl(UDir);
|
2009-02-04 03:21:40 +08:00
|
|
|
|
else
|
|
|
|
|
// Otherwise it is block-sope. using-directives will affect lookup
|
|
|
|
|
// only to the end of scope.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
S->PushUsingDirective(DeclPtrTy::make(UDir));
|
2008-12-30 11:27:21 +08:00
|
|
|
|
}
|
2008-10-07 01:10:33 +08:00
|
|
|
|
|
2009-06-20 08:51:54 +08:00
|
|
|
|
|
|
|
|
|
Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
|
2009-08-30 03:54:19 +08:00
|
|
|
|
AccessSpecifier AS,
|
2009-08-28 11:16:11 +08:00
|
|
|
|
SourceLocation UsingLoc,
|
|
|
|
|
const CXXScopeSpec &SS,
|
|
|
|
|
SourceLocation IdentLoc,
|
|
|
|
|
IdentifierInfo *TargetName,
|
|
|
|
|
OverloadedOperatorKind Op,
|
|
|
|
|
AttributeList *AttrList,
|
|
|
|
|
bool IsTypeName) {
|
2009-06-27 13:59:59 +08:00
|
|
|
|
assert((TargetName || Op) && "Invalid TargetName.");
|
2009-06-20 08:51:54 +08:00
|
|
|
|
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-27 08:27:47 +08:00
|
|
|
|
DeclarationName Name;
|
|
|
|
|
if (TargetName)
|
|
|
|
|
Name = TargetName;
|
|
|
|
|
else
|
|
|
|
|
Name = Context.DeclarationNames.getCXXOperatorName(Op);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
|
NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS, IdentLoc,
|
2009-08-28 13:40:36 +08:00
|
|
|
|
Name, AttrList, IsTypeName);
|
2009-08-30 03:54:19 +08:00
|
|
|
|
if (UD) {
|
2009-08-28 13:40:36 +08:00
|
|
|
|
PushOnScopeChains(UD, S);
|
2009-08-30 03:54:19 +08:00
|
|
|
|
UD->setAccess(AS);
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-28 13:40:36 +08:00
|
|
|
|
return DeclPtrTy::make(UD);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc,
|
|
|
|
|
const CXXScopeSpec &SS,
|
|
|
|
|
SourceLocation IdentLoc,
|
|
|
|
|
DeclarationName Name,
|
|
|
|
|
AttributeList *AttrList,
|
|
|
|
|
bool IsTypeName) {
|
|
|
|
|
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
|
|
|
|
|
assert(IdentLoc.isValid() && "Invalid TargetName location.");
|
2009-08-27 13:09:36 +08:00
|
|
|
|
|
2009-08-28 13:49:21 +08:00
|
|
|
|
// FIXME: We ignore attributes for now.
|
|
|
|
|
delete AttrList;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-28 11:16:11 +08:00
|
|
|
|
if (SS.isEmpty()) {
|
|
|
|
|
Diag(IdentLoc, diag::err_using_requires_qualname);
|
2009-08-28 13:40:36 +08:00
|
|
|
|
return 0;
|
2009-08-28 11:16:11 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
|
NestedNameSpecifier *NNS =
|
2009-08-28 11:16:11 +08:00
|
|
|
|
static_cast<NestedNameSpecifier *>(SS.getScopeRep());
|
2009-06-20 08:51:54 +08:00
|
|
|
|
|
2009-08-28 13:49:21 +08:00
|
|
|
|
if (isUnknownSpecialization(SS)) {
|
|
|
|
|
return UnresolvedUsingDecl::Create(Context, CurContext, UsingLoc,
|
|
|
|
|
SS.getRange(), NNS,
|
|
|
|
|
IdentLoc, Name, IsTypeName);
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-28 11:16:11 +08:00
|
|
|
|
DeclContext *LookupContext = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-28 11:16:11 +08:00
|
|
|
|
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) {
|
|
|
|
|
// C++0x N2914 [namespace.udecl]p3:
|
|
|
|
|
// A using-declaration used as a member-declaration shall refer to a member
|
|
|
|
|
// of a base class of the class being defined, shall refer to a member of an
|
|
|
|
|
// anonymous union that is a member of a base class of the class being
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// defined, or shall refer to an enumerator for an enumeration type that is
|
2009-08-28 11:16:11 +08:00
|
|
|
|
// a member of a base class of the class being defined.
|
|
|
|
|
const Type *Ty = NNS->getAsType();
|
|
|
|
|
if (!Ty || !IsDerivedFrom(Context.getTagDeclType(RD), QualType(Ty, 0))) {
|
|
|
|
|
Diag(SS.getRange().getBegin(),
|
|
|
|
|
diag::err_using_decl_nested_name_specifier_is_not_a_base_class)
|
|
|
|
|
<< NNS << RD->getDeclName();
|
2009-08-28 13:40:36 +08:00
|
|
|
|
return 0;
|
2009-06-20 08:51:54 +08:00
|
|
|
|
}
|
2009-08-28 23:18:15 +08:00
|
|
|
|
|
|
|
|
|
QualType BaseTy = Context.getCanonicalType(QualType(Ty, 0));
|
|
|
|
|
LookupContext = BaseTy->getAs<RecordType>()->getDecl();
|
2009-06-20 08:51:54 +08:00
|
|
|
|
} else {
|
2009-08-28 11:16:11 +08:00
|
|
|
|
// C++0x N2914 [namespace.udecl]p8:
|
|
|
|
|
// A using-declaration for a class member shall be a member-declaration.
|
|
|
|
|
if (NNS->getKind() == NestedNameSpecifier::TypeSpec) {
|
2009-08-28 11:35:18 +08:00
|
|
|
|
Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_class_member)
|
2009-08-28 11:16:11 +08:00
|
|
|
|
<< SS.getRange();
|
2009-08-28 13:40:36 +08:00
|
|
|
|
return 0;
|
2009-08-28 11:16:11 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-28 11:16:11 +08:00
|
|
|
|
// C++0x N2914 [namespace.udecl]p9:
|
|
|
|
|
// In a using-declaration, a prefix :: refers to the global namespace.
|
|
|
|
|
if (NNS->getKind() == NestedNameSpecifier::Global)
|
|
|
|
|
LookupContext = Context.getTranslationUnitDecl();
|
|
|
|
|
else
|
|
|
|
|
LookupContext = NNS->getAsNamespace();
|
2009-06-20 08:51:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-28 11:16:11 +08:00
|
|
|
|
|
|
|
|
|
// Lookup target name.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
LookupResult R = LookupQualifiedName(LookupContext,
|
2009-08-28 11:16:11 +08:00
|
|
|
|
Name, LookupOrdinaryName);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-28 11:16:11 +08:00
|
|
|
|
if (!R) {
|
2009-08-30 08:58:45 +08:00
|
|
|
|
DiagnoseMissingMember(IdentLoc, Name, NNS, SS.getRange());
|
2009-08-28 13:40:36 +08:00
|
|
|
|
return 0;
|
2009-08-28 11:16:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NamedDecl *ND = R.getAsDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-28 11:16:11 +08:00
|
|
|
|
if (IsTypeName && !isa<TypeDecl>(ND)) {
|
|
|
|
|
Diag(IdentLoc, diag::err_using_typename_non_type);
|
2009-08-28 13:40:36 +08:00
|
|
|
|
return 0;
|
2009-08-28 11:16:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-28 11:35:18 +08:00
|
|
|
|
// C++0x N2914 [namespace.udecl]p6:
|
|
|
|
|
// A using-declaration shall not name a namespace.
|
|
|
|
|
if (isa<NamespaceDecl>(ND)) {
|
|
|
|
|
Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
|
|
|
|
|
<< SS.getRange();
|
2009-08-28 13:40:36 +08:00
|
|
|
|
return 0;
|
2009-08-28 11:35:18 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-28 13:40:36 +08:00
|
|
|
|
return UsingDecl::Create(Context, CurContext, IdentLoc, SS.getRange(),
|
|
|
|
|
ND->getLocation(), UsingLoc, ND, NNS, IsTypeName);
|
2009-06-20 08:51:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-03-29 07:53:49 +08:00
|
|
|
|
/// getNamespaceDecl - Returns the namespace a decl represents. If the decl
|
|
|
|
|
/// is a namespace alias, returns the namespace it points to.
|
|
|
|
|
static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) {
|
|
|
|
|
if (NamespaceAliasDecl *AD = dyn_cast_or_null<NamespaceAliasDecl>(D))
|
|
|
|
|
return AD->getNamespace();
|
|
|
|
|
return dyn_cast_or_null<NamespaceDecl>(D);
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
|
2009-03-29 06:53:22 +08:00
|
|
|
|
SourceLocation NamespaceLoc,
|
2009-03-29 03:18:32 +08:00
|
|
|
|
SourceLocation AliasLoc,
|
|
|
|
|
IdentifierInfo *Alias,
|
|
|
|
|
const CXXScopeSpec &SS,
|
2009-03-29 06:53:22 +08:00
|
|
|
|
SourceLocation IdentLoc,
|
|
|
|
|
IdentifierInfo *Ident) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-29 07:53:49 +08:00
|
|
|
|
// Lookup the namespace name.
|
|
|
|
|
LookupResult R = LookupParsedName(S, &SS, Ident, LookupNamespaceName, false);
|
|
|
|
|
|
2009-03-28 14:23:46 +08:00
|
|
|
|
// Check if we have a previous declaration with the same name.
|
2009-03-29 07:49:35 +08:00
|
|
|
|
if (NamedDecl *PrevDecl = LookupName(S, Alias, LookupOrdinaryName, true)) {
|
2009-03-29 07:53:49 +08:00
|
|
|
|
if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// We already have an alias with the same name that points to the same
|
2009-03-29 07:53:49 +08:00
|
|
|
|
// namespace, so don't create a new one.
|
|
|
|
|
if (!R.isAmbiguous() && AD->getNamespace() == getNamespaceDecl(R))
|
|
|
|
|
return DeclPtrTy();
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-28 14:23:46 +08:00
|
|
|
|
unsigned DiagID = isa<NamespaceDecl>(PrevDecl) ? diag::err_redefinition :
|
|
|
|
|
diag::err_redefinition_different_kind;
|
|
|
|
|
Diag(AliasLoc, DiagID) << Alias;
|
|
|
|
|
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
2009-03-29 03:18:32 +08:00
|
|
|
|
return DeclPtrTy();
|
2009-03-28 14:23:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-03-28 14:42:02 +08:00
|
|
|
|
if (R.isAmbiguous()) {
|
2009-03-29 06:53:22 +08:00
|
|
|
|
DiagnoseAmbiguousLookup(R, Ident, IdentLoc);
|
2009-03-29 03:18:32 +08:00
|
|
|
|
return DeclPtrTy();
|
2009-03-28 14:42:02 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-28 14:42:02 +08:00
|
|
|
|
if (!R) {
|
|
|
|
|
Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange();
|
2009-03-29 03:18:32 +08:00
|
|
|
|
return DeclPtrTy();
|
2009-03-28 14:42:02 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-20 03:55:27 +08:00
|
|
|
|
NamespaceAliasDecl *AliasDecl =
|
2009-09-09 23:08:12 +08:00
|
|
|
|
NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
|
|
|
|
|
Alias, SS.getRange(),
|
2009-05-30 14:48:27 +08:00
|
|
|
|
(NestedNameSpecifier *)SS.getScopeRep(),
|
2009-03-29 06:58:02 +08:00
|
|
|
|
IdentLoc, R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-30 10:36:12 +08:00
|
|
|
|
CurContext->addDecl(AliasDecl);
|
2009-03-29 06:58:02 +08:00
|
|
|
|
return DeclPtrTy::make(AliasDecl);
|
2009-03-28 13:27:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-06-20 03:55:27 +08:00
|
|
|
|
void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
|
|
|
|
|
CXXConstructorDecl *Constructor) {
|
2009-06-23 04:37:23 +08:00
|
|
|
|
assert((Constructor->isImplicit() && Constructor->isDefaultConstructor() &&
|
|
|
|
|
!Constructor->isUsed()) &&
|
|
|
|
|
"DefineImplicitDefaultConstructor - call it for implicit default ctor");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-20 03:55:27 +08:00
|
|
|
|
CXXRecordDecl *ClassDecl
|
|
|
|
|
= cast<CXXRecordDecl>(Constructor->getDeclContext());
|
2009-06-23 07:34:40 +08:00
|
|
|
|
assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// Before the implicitly-declared default constructor for a class is
|
2009-06-20 03:55:27 +08:00
|
|
|
|
// implicitly defined, all the implicitly-declared default constructors
|
|
|
|
|
// for its base class and its non-static data members shall have been
|
|
|
|
|
// implicitly defined.
|
|
|
|
|
bool err = false;
|
2009-07-01 00:36:53 +08:00
|
|
|
|
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
|
|
|
|
|
E = ClassDecl->bases_end(); Base != E; ++Base) {
|
2009-06-20 03:55:27 +08:00
|
|
|
|
CXXRecordDecl *BaseClassDecl
|
2009-07-30 05:53:49 +08:00
|
|
|
|
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
2009-06-20 03:55:27 +08:00
|
|
|
|
if (!BaseClassDecl->hasTrivialConstructor()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CXXConstructorDecl *BaseCtor =
|
2009-06-24 07:42:10 +08:00
|
|
|
|
BaseClassDecl->getDefaultConstructor(Context))
|
|
|
|
|
MarkDeclarationReferenced(CurrentLocation, BaseCtor);
|
2009-06-20 03:55:27 +08:00
|
|
|
|
else {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(CurrentLocation, diag::err_defining_default_ctor)
|
|
|
|
|
<< Context.getTagDeclType(ClassDecl) << 1
|
2009-06-21 04:23:38 +08:00
|
|
|
|
<< Context.getTagDeclType(BaseClassDecl);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(BaseClassDecl->getLocation(), diag::note_previous_class_decl)
|
2009-06-21 04:23:38 +08:00
|
|
|
|
<< Context.getTagDeclType(BaseClassDecl);
|
2009-06-20 03:55:27 +08:00
|
|
|
|
err = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-07-01 00:36:53 +08:00
|
|
|
|
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
|
|
|
|
|
E = ClassDecl->field_end(); Field != E; ++Field) {
|
2009-06-20 03:55:27 +08:00
|
|
|
|
QualType FieldType = Context.getCanonicalType((*Field)->getType());
|
|
|
|
|
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
|
|
|
|
|
FieldType = Array->getElementType();
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
|
2009-06-20 03:55:27 +08:00
|
|
|
|
CXXRecordDecl *FieldClassDecl
|
|
|
|
|
= cast<CXXRecordDecl>(FieldClassType->getDecl());
|
2009-06-25 17:03:06 +08:00
|
|
|
|
if (!FieldClassDecl->hasTrivialConstructor()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CXXConstructorDecl *FieldCtor =
|
2009-06-24 07:42:10 +08:00
|
|
|
|
FieldClassDecl->getDefaultConstructor(Context))
|
|
|
|
|
MarkDeclarationReferenced(CurrentLocation, FieldCtor);
|
2009-06-20 03:55:27 +08:00
|
|
|
|
else {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(CurrentLocation, diag::err_defining_default_ctor)
|
2009-06-21 04:23:38 +08:00
|
|
|
|
<< Context.getTagDeclType(ClassDecl) << 0 <<
|
|
|
|
|
Context.getTagDeclType(FieldClassDecl);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(FieldClassDecl->getLocation(), diag::note_previous_class_decl)
|
2009-06-21 04:23:38 +08:00
|
|
|
|
<< Context.getTagDeclType(FieldClassDecl);
|
2009-06-20 03:55:27 +08:00
|
|
|
|
err = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-08-05 05:02:39 +08:00
|
|
|
|
} else if (FieldType->isReferenceType()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(CurrentLocation, diag::err_unintialized_member)
|
2009-07-10 01:37:12 +08:00
|
|
|
|
<< Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
|
2009-06-20 03:55:27 +08:00
|
|
|
|
Diag((*Field)->getLocation(), diag::note_declared_at);
|
|
|
|
|
err = true;
|
2009-08-05 05:02:39 +08:00
|
|
|
|
} else if (FieldType.isConstQualified()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(CurrentLocation, diag::err_unintialized_member)
|
2009-07-10 01:37:12 +08:00
|
|
|
|
<< Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
|
2009-06-20 03:55:27 +08:00
|
|
|
|
Diag((*Field)->getLocation(), diag::note_declared_at);
|
|
|
|
|
err = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!err)
|
2009-06-27 00:08:57 +08:00
|
|
|
|
Constructor->setUsed();
|
|
|
|
|
else
|
|
|
|
|
Constructor->setInvalidDecl();
|
2009-06-20 03:55:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-06-27 07:49:16 +08:00
|
|
|
|
void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
|
2009-09-05 03:04:08 +08:00
|
|
|
|
CXXDestructorDecl *Destructor) {
|
2009-06-27 07:49:16 +08:00
|
|
|
|
assert((Destructor->isImplicit() && !Destructor->isUsed()) &&
|
|
|
|
|
"DefineImplicitDestructor - call it for implicit default dtor");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-27 07:49:16 +08:00
|
|
|
|
CXXRecordDecl *ClassDecl
|
|
|
|
|
= cast<CXXRecordDecl>(Destructor->getDeclContext());
|
|
|
|
|
assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
|
|
|
|
|
// C++ [class.dtor] p5
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// Before the implicitly-declared default destructor for a class is
|
2009-06-27 07:49:16 +08:00
|
|
|
|
// implicitly defined, all the implicitly-declared default destructors
|
|
|
|
|
// for its base class and its non-static data members shall have been
|
|
|
|
|
// implicitly defined.
|
2009-07-01 00:36:53 +08:00
|
|
|
|
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
|
|
|
|
|
E = ClassDecl->bases_end(); Base != E; ++Base) {
|
2009-06-27 07:49:16 +08:00
|
|
|
|
CXXRecordDecl *BaseClassDecl
|
2009-07-30 05:53:49 +08:00
|
|
|
|
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
2009-06-27 07:49:16 +08:00
|
|
|
|
if (!BaseClassDecl->hasTrivialDestructor()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CXXDestructorDecl *BaseDtor =
|
2009-06-27 07:49:16 +08:00
|
|
|
|
const_cast<CXXDestructorDecl*>(BaseClassDecl->getDestructor(Context)))
|
|
|
|
|
MarkDeclarationReferenced(CurrentLocation, BaseDtor);
|
|
|
|
|
else
|
2009-09-09 23:08:12 +08:00
|
|
|
|
assert(false &&
|
2009-06-27 07:49:16 +08:00
|
|
|
|
"DefineImplicitDestructor - missing dtor in a base class");
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-07-01 00:36:53 +08:00
|
|
|
|
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
|
|
|
|
|
E = ClassDecl->field_end(); Field != E; ++Field) {
|
2009-06-27 07:49:16 +08:00
|
|
|
|
QualType FieldType = Context.getCanonicalType((*Field)->getType());
|
|
|
|
|
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
|
|
|
|
|
FieldType = Array->getElementType();
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
|
2009-06-27 07:49:16 +08:00
|
|
|
|
CXXRecordDecl *FieldClassDecl
|
|
|
|
|
= cast<CXXRecordDecl>(FieldClassType->getDecl());
|
|
|
|
|
if (!FieldClassDecl->hasTrivialDestructor()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CXXDestructorDecl *FieldDtor =
|
2009-06-27 07:49:16 +08:00
|
|
|
|
const_cast<CXXDestructorDecl*>(
|
|
|
|
|
FieldClassDecl->getDestructor(Context)))
|
|
|
|
|
MarkDeclarationReferenced(CurrentLocation, FieldDtor);
|
|
|
|
|
else
|
2009-09-09 23:08:12 +08:00
|
|
|
|
assert(false &&
|
2009-06-27 07:49:16 +08:00
|
|
|
|
"DefineImplicitDestructor - missing dtor in class of a data member");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Destructor->setUsed();
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-26 05:45:19 +08:00
|
|
|
|
void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
|
|
|
|
|
CXXMethodDecl *MethodDecl) {
|
|
|
|
|
assert((MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() &&
|
|
|
|
|
MethodDecl->getOverloadedOperator() == OO_Equal &&
|
|
|
|
|
!MethodDecl->isUsed()) &&
|
|
|
|
|
"DefineImplicitOverloadedAssign - call it for implicit assignment op");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-26 05:45:19 +08:00
|
|
|
|
CXXRecordDecl *ClassDecl
|
|
|
|
|
= cast<CXXRecordDecl>(MethodDecl->getDeclContext());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-27 00:08:57 +08:00
|
|
|
|
// C++[class.copy] p12
|
2009-06-26 05:45:19 +08:00
|
|
|
|
// Before the implicitly-declared copy assignment operator for a class is
|
|
|
|
|
// implicitly defined, all implicitly-declared copy assignment operators
|
|
|
|
|
// for its direct base classes and its nonstatic data members shall have
|
|
|
|
|
// been implicitly defined.
|
|
|
|
|
bool err = false;
|
2009-07-01 00:36:53 +08:00
|
|
|
|
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
|
|
|
|
|
E = ClassDecl->bases_end(); Base != E; ++Base) {
|
2009-06-26 05:45:19 +08:00
|
|
|
|
CXXRecordDecl *BaseClassDecl
|
2009-07-30 05:53:49 +08:00
|
|
|
|
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CXXMethodDecl *BaseAssignOpMethod =
|
2009-06-26 05:45:19 +08:00
|
|
|
|
getAssignOperatorMethod(MethodDecl->getParamDecl(0), BaseClassDecl))
|
|
|
|
|
MarkDeclarationReferenced(CurrentLocation, BaseAssignOpMethod);
|
|
|
|
|
}
|
2009-07-01 00:36:53 +08:00
|
|
|
|
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
|
|
|
|
|
E = ClassDecl->field_end(); Field != E; ++Field) {
|
2009-06-26 05:45:19 +08:00
|
|
|
|
QualType FieldType = Context.getCanonicalType((*Field)->getType());
|
|
|
|
|
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
|
|
|
|
|
FieldType = Array->getElementType();
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
|
2009-06-26 05:45:19 +08:00
|
|
|
|
CXXRecordDecl *FieldClassDecl
|
|
|
|
|
= cast<CXXRecordDecl>(FieldClassType->getDecl());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CXXMethodDecl *FieldAssignOpMethod =
|
2009-06-26 05:45:19 +08:00
|
|
|
|
getAssignOperatorMethod(MethodDecl->getParamDecl(0), FieldClassDecl))
|
|
|
|
|
MarkDeclarationReferenced(CurrentLocation, FieldAssignOpMethod);
|
2009-08-05 05:02:39 +08:00
|
|
|
|
} else if (FieldType->isReferenceType()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
|
2009-07-10 01:47:25 +08:00
|
|
|
|
<< Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
|
|
|
|
|
Diag(Field->getLocation(), diag::note_declared_at);
|
2009-06-26 05:45:19 +08:00
|
|
|
|
Diag(CurrentLocation, diag::note_first_required_here);
|
|
|
|
|
err = true;
|
2009-08-05 05:02:39 +08:00
|
|
|
|
} else if (FieldType.isConstQualified()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
|
2009-07-10 01:47:25 +08:00
|
|
|
|
<< Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
|
|
|
|
|
Diag(Field->getLocation(), diag::note_declared_at);
|
2009-06-26 05:45:19 +08:00
|
|
|
|
Diag(CurrentLocation, diag::note_first_required_here);
|
|
|
|
|
err = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!err)
|
2009-09-09 23:08:12 +08:00
|
|
|
|
MethodDecl->setUsed();
|
2009-06-26 05:45:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CXXMethodDecl *
|
|
|
|
|
Sema::getAssignOperatorMethod(ParmVarDecl *ParmDecl,
|
|
|
|
|
CXXRecordDecl *ClassDecl) {
|
|
|
|
|
QualType LHSType = Context.getTypeDeclType(ClassDecl);
|
|
|
|
|
QualType RHSType(LHSType);
|
|
|
|
|
// If class's assignment operator argument is const/volatile qualified,
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// look for operator = (const/volatile B&). Otherwise, look for
|
2009-06-26 05:45:19 +08:00
|
|
|
|
// operator = (B&).
|
|
|
|
|
if (ParmDecl->getType().isConstQualified())
|
|
|
|
|
RHSType.addConst();
|
|
|
|
|
if (ParmDecl->getType().isVolatileQualified())
|
|
|
|
|
RHSType.addVolatile();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
ExprOwningPtr<Expr> LHS(this, new (Context) DeclRefExpr(ParmDecl,
|
|
|
|
|
LHSType,
|
2009-06-26 05:45:19 +08:00
|
|
|
|
SourceLocation()));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
ExprOwningPtr<Expr> RHS(this, new (Context) DeclRefExpr(ParmDecl,
|
|
|
|
|
RHSType,
|
2009-06-26 05:45:19 +08:00
|
|
|
|
SourceLocation()));
|
|
|
|
|
Expr *Args[2] = { &*LHS, &*RHS };
|
|
|
|
|
OverloadCandidateSet CandidateSet;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
AddMemberOperatorCandidates(clang::OO_Equal, SourceLocation(), Args, 2,
|
2009-06-26 05:45:19 +08:00
|
|
|
|
CandidateSet);
|
|
|
|
|
OverloadCandidateSet::iterator Best;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (BestViableFunction(CandidateSet,
|
2009-06-26 05:45:19 +08:00
|
|
|
|
ClassDecl->getLocation(), Best) == OR_Success)
|
|
|
|
|
return cast<CXXMethodDecl>(Best->Function);
|
|
|
|
|
assert(false &&
|
|
|
|
|
"getAssignOperatorMethod - copy assignment operator method not found");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-23 07:34:40 +08:00
|
|
|
|
void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
|
|
|
|
|
CXXConstructorDecl *CopyConstructor,
|
|
|
|
|
unsigned TypeQuals) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
assert((CopyConstructor->isImplicit() &&
|
2009-06-23 07:34:40 +08:00
|
|
|
|
CopyConstructor->isCopyConstructor(Context, TypeQuals) &&
|
|
|
|
|
!CopyConstructor->isUsed()) &&
|
|
|
|
|
"DefineImplicitCopyConstructor - call it for implicit copy ctor");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-23 07:34:40 +08:00
|
|
|
|
CXXRecordDecl *ClassDecl
|
|
|
|
|
= cast<CXXRecordDecl>(CopyConstructor->getDeclContext());
|
|
|
|
|
assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
|
2009-06-24 07:42:10 +08:00
|
|
|
|
// C++ [class.copy] p209
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// Before the implicitly-declared copy constructor for a class is
|
2009-06-23 07:34:40 +08:00
|
|
|
|
// implicitly defined, all the implicitly-declared copy constructors
|
|
|
|
|
// for its base class and its non-static data members shall have been
|
|
|
|
|
// implicitly defined.
|
|
|
|
|
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
|
|
|
|
|
Base != ClassDecl->bases_end(); ++Base) {
|
|
|
|
|
CXXRecordDecl *BaseClassDecl
|
2009-07-30 05:53:49 +08:00
|
|
|
|
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CXXConstructorDecl *BaseCopyCtor =
|
2009-06-23 07:34:40 +08:00
|
|
|
|
BaseClassDecl->getCopyConstructor(Context, TypeQuals))
|
2009-06-24 07:42:10 +08:00
|
|
|
|
MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor);
|
2009-06-23 07:34:40 +08:00
|
|
|
|
}
|
2009-06-30 10:36:12 +08:00
|
|
|
|
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
|
|
|
|
|
FieldEnd = ClassDecl->field_end();
|
|
|
|
|
Field != FieldEnd; ++Field) {
|
2009-06-23 07:34:40 +08:00
|
|
|
|
QualType FieldType = Context.getCanonicalType((*Field)->getType());
|
|
|
|
|
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
|
|
|
|
|
FieldType = Array->getElementType();
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
|
2009-06-23 07:34:40 +08:00
|
|
|
|
CXXRecordDecl *FieldClassDecl
|
|
|
|
|
= cast<CXXRecordDecl>(FieldClassType->getDecl());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CXXConstructorDecl *FieldCopyCtor =
|
2009-06-23 07:34:40 +08:00
|
|
|
|
FieldClassDecl->getCopyConstructor(Context, TypeQuals))
|
2009-06-24 07:42:10 +08:00
|
|
|
|
MarkDeclarationReferenced(CurrentLocation, FieldCopyCtor);
|
2009-06-23 07:34:40 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
CopyConstructor->setUsed();
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-25 13:12:04 +08:00
|
|
|
|
Sema::OwningExprResult
|
2009-09-05 15:40:38 +08:00
|
|
|
|
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CXXConstructorDecl *Constructor,
|
2009-09-08 06:23:31 +08:00
|
|
|
|
MultiExprArg ExprArgs) {
|
2009-08-16 13:13:48 +08:00
|
|
|
|
bool Elidable = false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-10 07:08:42 +08:00
|
|
|
|
// C++ [class.copy]p15:
|
|
|
|
|
// Whenever a temporary class object is copied using a copy constructor, and
|
|
|
|
|
// this object and the copy have the same cv-unqualified type, an
|
|
|
|
|
// implementation is permitted to treat the original and the copy as two
|
|
|
|
|
// different ways of referring to the same object and not perform a copy at
|
|
|
|
|
// all, even if the class copy constructor or destructor have side effects.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-16 13:13:48 +08:00
|
|
|
|
// FIXME: Is this enough?
|
2009-09-10 07:08:42 +08:00
|
|
|
|
if (Constructor->isCopyConstructor(Context)) {
|
2009-09-08 06:23:31 +08:00
|
|
|
|
Expr *E = ((Expr **)ExprArgs.get())[0];
|
2009-08-16 13:13:48 +08:00
|
|
|
|
while (CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(E))
|
|
|
|
|
E = BE->getSubExpr();
|
2009-09-10 07:08:42 +08:00
|
|
|
|
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
|
|
|
|
|
if (ICE->getCastKind() == CastExpr::CK_NoOp)
|
|
|
|
|
E = ICE->getSubExpr();
|
|
|
|
|
|
2009-08-16 13:13:48 +08:00
|
|
|
|
if (isa<CallExpr>(E) || isa<CXXTemporaryObjectExpr>(E))
|
|
|
|
|
Elidable = true;
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
|
return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor,
|
2009-09-08 06:23:31 +08:00
|
|
|
|
Elidable, move(ExprArgs));
|
2009-08-16 13:13:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-06 01:03:54 +08:00
|
|
|
|
/// BuildCXXConstructExpr - Creates a complete call to a constructor,
|
|
|
|
|
/// including handling of its default argument expressions.
|
2009-08-25 13:12:04 +08:00
|
|
|
|
Sema::OwningExprResult
|
2009-09-05 15:40:38 +08:00
|
|
|
|
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
|
|
|
|
|
CXXConstructorDecl *Constructor, bool Elidable,
|
2009-09-08 06:23:31 +08:00
|
|
|
|
MultiExprArg ExprArgs) {
|
|
|
|
|
unsigned NumExprs = ExprArgs.size();
|
|
|
|
|
Expr **Exprs = (Expr **)ExprArgs.release();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-10 07:08:42 +08:00
|
|
|
|
return Owned(CXXConstructExpr::Create(Context, DeclInitType, Constructor,
|
|
|
|
|
Elidable, Exprs, NumExprs));
|
2009-08-06 01:03:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-27 13:08:22 +08:00
|
|
|
|
Sema::OwningExprResult
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Sema::BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Constructor,
|
|
|
|
|
QualType Ty,
|
|
|
|
|
SourceLocation TyBeginLoc,
|
2009-08-27 13:08:22 +08:00
|
|
|
|
MultiExprArg Args,
|
|
|
|
|
SourceLocation RParenLoc) {
|
2009-09-10 07:08:42 +08:00
|
|
|
|
unsigned NumExprs = Args.size();
|
|
|
|
|
Expr **Exprs = (Expr **)Args.release();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-10 07:08:42 +08:00
|
|
|
|
return Owned(new (Context) CXXTemporaryObjectExpr(Context, Constructor, Ty,
|
|
|
|
|
TyBeginLoc, Exprs,
|
|
|
|
|
NumExprs, RParenLoc));
|
2009-08-27 13:08:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
bool Sema::InitializeVarWithConstructor(VarDecl *VD,
|
2009-08-06 01:03:54 +08:00
|
|
|
|
CXXConstructorDecl *Constructor,
|
2009-09-09 23:08:12 +08:00
|
|
|
|
QualType DeclInitType,
|
2009-09-08 06:23:31 +08:00
|
|
|
|
MultiExprArg Exprs) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
OwningExprResult TempResult =
|
|
|
|
|
BuildCXXConstructExpr(VD->getLocation(), DeclInitType, Constructor,
|
2009-09-08 06:23:31 +08:00
|
|
|
|
move(Exprs));
|
2009-08-25 13:18:00 +08:00
|
|
|
|
if (TempResult.isInvalid())
|
|
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-25 13:12:04 +08:00
|
|
|
|
Expr *Temp = TempResult.takeAs<Expr>();
|
2009-06-23 07:06:13 +08:00
|
|
|
|
MarkDeclarationReferenced(VD->getLocation(), Constructor);
|
2009-08-06 02:17:32 +08:00
|
|
|
|
Temp = MaybeCreateCXXExprWithTemporaries(Temp, /*DestroyTemps=*/true);
|
2009-05-27 02:54:04 +08:00
|
|
|
|
VD->setInit(Context, Temp);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-25 13:18:00 +08:00
|
|
|
|
return false;
|
2009-04-17 07:50:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
void Sema::FinalizeVarWithDestructor(VarDecl *VD, QualType DeclInitType) {
|
2009-06-27 07:49:16 +08:00
|
|
|
|
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(
|
2009-07-30 05:53:49 +08:00
|
|
|
|
DeclInitType->getAs<RecordType>()->getDecl());
|
2009-06-27 07:49:16 +08:00
|
|
|
|
if (!ClassDecl->hasTrivialDestructor())
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CXXDestructorDecl *Destructor =
|
2009-06-27 07:49:16 +08:00
|
|
|
|
const_cast<CXXDestructorDecl*>(ClassDecl->getDestructor(Context)))
|
2009-08-04 03:13:25 +08:00
|
|
|
|
MarkDeclarationReferenced(VD->getLocation(), Destructor);
|
2009-06-27 07:49:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
/// AddCXXDirectInitializerToDecl - This action is called immediately after
|
2008-10-07 01:10:33 +08:00
|
|
|
|
/// ActOnDeclarator, when a C++ direct initializer is present.
|
|
|
|
|
/// e.g: "int x(1);"
|
2009-03-29 03:18:32 +08:00
|
|
|
|
void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
|
|
|
|
|
SourceLocation LParenLoc,
|
2009-03-16 01:47:39 +08:00
|
|
|
|
MultiExprArg Exprs,
|
2008-10-07 01:10:33 +08:00
|
|
|
|
SourceLocation *CommaLocs,
|
|
|
|
|
SourceLocation RParenLoc) {
|
2009-03-16 01:47:39 +08:00
|
|
|
|
unsigned NumExprs = Exprs.size();
|
|
|
|
|
assert(NumExprs != 0 && Exprs.get() && "missing expressions");
|
2009-03-29 03:18:32 +08:00
|
|
|
|
Decl *RealDecl = Dcl.getAs<Decl>();
|
2008-10-07 01:10:33 +08:00
|
|
|
|
|
|
|
|
|
// If there is no declaration, there was an error parsing it. Just ignore
|
|
|
|
|
// the initializer.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
if (RealDecl == 0)
|
2008-10-07 01:10:33 +08:00
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2008-10-07 01:10:33 +08:00
|
|
|
|
VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl);
|
|
|
|
|
if (!VDecl) {
|
|
|
|
|
Diag(RealDecl->getLocation(), diag::err_illegal_initializer);
|
|
|
|
|
RealDecl->setInvalidDecl();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-27 05:14:46 +08:00
|
|
|
|
// We will represent direct-initialization similarly to copy-initialization:
|
2008-10-07 07:08:37 +08:00
|
|
|
|
// int x(1); -as-> int x = 1;
|
2008-10-07 01:10:33 +08:00
|
|
|
|
// ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c);
|
|
|
|
|
//
|
|
|
|
|
// Clients that want to distinguish between the two forms, can check for
|
|
|
|
|
// direct initializer using VarDecl::hasCXXDirectInitializer().
|
|
|
|
|
// A major benefit is that clients that don't particularly care about which
|
|
|
|
|
// exactly form was it (like the CodeGen) can handle both cases without
|
|
|
|
|
// special case code.
|
2008-10-07 02:37:09 +08:00
|
|
|
|
|
2009-08-27 05:14:46 +08:00
|
|
|
|
// If either the declaration has a dependent type or if any of the expressions
|
|
|
|
|
// is type-dependent, we represent the initialization via a ParenListExpr for
|
|
|
|
|
// later use during template instantiation.
|
|
|
|
|
if (VDecl->getType()->isDependentType() ||
|
|
|
|
|
Expr::hasAnyTypeDependentArguments((Expr **)Exprs.get(), Exprs.size())) {
|
|
|
|
|
// Let clients know that initialization was done with a direct initializer.
|
|
|
|
|
VDecl->setCXXDirectInitializer(true);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-27 05:14:46 +08:00
|
|
|
|
// Store the initialization expressions as a ParenListExpr.
|
|
|
|
|
unsigned NumExprs = Exprs.size();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
VDecl->setInit(Context,
|
2009-08-27 05:14:46 +08:00
|
|
|
|
new (Context) ParenListExpr(Context, LParenLoc,
|
|
|
|
|
(Expr **)Exprs.release(),
|
|
|
|
|
NumExprs, RParenLoc));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-08-27 05:14:46 +08:00
|
|
|
|
|
2008-10-07 01:10:33 +08:00
|
|
|
|
// C++ 8.5p11:
|
|
|
|
|
// The form of initialization (using parentheses or '=') is generally
|
|
|
|
|
// insignificant, but does matter when the entity being initialized has a
|
2008-10-07 02:37:09 +08:00
|
|
|
|
// class type.
|
2008-11-04 04:45:27 +08:00
|
|
|
|
QualType DeclInitType = VDecl->getType();
|
|
|
|
|
if (const ArrayType *Array = Context.getAsArrayType(DeclInitType))
|
|
|
|
|
DeclInitType = Array->getElementType();
|
2008-10-07 02:37:09 +08:00
|
|
|
|
|
2009-03-25 00:43:20 +08:00
|
|
|
|
// FIXME: This isn't the right place to complete the type.
|
|
|
|
|
if (RequireCompleteType(VDecl->getLocation(), VDecl->getType(),
|
|
|
|
|
diag::err_typecheck_decl_incomplete_type)) {
|
|
|
|
|
VDecl->setInvalidDecl();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-07 02:37:09 +08:00
|
|
|
|
if (VDecl->getType()->isRecordType()) {
|
2009-09-10 07:08:42 +08:00
|
|
|
|
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
|
|
|
|
|
|
2008-11-04 04:45:27 +08:00
|
|
|
|
CXXConstructorDecl *Constructor
|
2009-03-16 01:47:39 +08:00
|
|
|
|
= PerformInitializationByConstructor(DeclInitType,
|
2009-09-10 07:08:42 +08:00
|
|
|
|
move(Exprs),
|
2008-11-05 23:29:30 +08:00
|
|
|
|
VDecl->getLocation(),
|
|
|
|
|
SourceRange(VDecl->getLocation(),
|
|
|
|
|
RParenLoc),
|
2008-11-24 13:29:24 +08:00
|
|
|
|
VDecl->getDeclName(),
|
2009-09-10 07:08:42 +08:00
|
|
|
|
IK_Direct,
|
|
|
|
|
ConstructorArgs);
|
2009-03-16 01:47:39 +08:00
|
|
|
|
if (!Constructor)
|
2008-11-04 04:45:27 +08:00
|
|
|
|
RealDecl->setInvalidDecl();
|
2009-04-16 05:48:18 +08:00
|
|
|
|
else {
|
|
|
|
|
VDecl->setCXXDirectInitializer(true);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (InitializeVarWithConstructor(VDecl, Constructor, DeclInitType,
|
2009-09-10 07:08:42 +08:00
|
|
|
|
move_arg(ConstructorArgs)))
|
2009-08-25 13:18:00 +08:00
|
|
|
|
RealDecl->setInvalidDecl();
|
2009-08-04 03:13:25 +08:00
|
|
|
|
FinalizeVarWithDestructor(VDecl, DeclInitType);
|
2009-04-16 05:48:18 +08:00
|
|
|
|
}
|
2008-10-07 02:37:09 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
2008-10-07 01:10:33 +08:00
|
|
|
|
|
2008-10-07 07:08:37 +08:00
|
|
|
|
if (NumExprs > 1) {
|
2008-11-19 13:27:50 +08:00
|
|
|
|
Diag(CommaLocs[0], diag::err_builtin_direct_init_more_than_one_arg)
|
|
|
|
|
<< SourceRange(VDecl->getLocation(), RParenLoc);
|
2008-10-07 01:10:33 +08:00
|
|
|
|
RealDecl->setInvalidDecl();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Let clients know that initialization was done with a direct initializer.
|
|
|
|
|
VDecl->setCXXDirectInitializer(true);
|
2008-10-07 07:08:37 +08:00
|
|
|
|
|
|
|
|
|
assert(NumExprs == 1 && "Expected 1 expression");
|
|
|
|
|
// Set the init expression, handles conversions.
|
2009-03-16 01:47:39 +08:00
|
|
|
|
AddInitializerToDecl(Dcl, ExprArg(*this, Exprs.release()[0]),
|
|
|
|
|
/*DirectInit=*/true);
|
2008-10-07 01:10:33 +08:00
|
|
|
|
}
|
2008-10-29 08:13:59 +08:00
|
|
|
|
|
2009-09-10 07:08:42 +08:00
|
|
|
|
/// \brief Perform initialization by constructor (C++ [dcl.init]p14), which
|
|
|
|
|
/// may occur as part of direct-initialization or copy-initialization.
|
|
|
|
|
///
|
|
|
|
|
/// \param ClassType the type of the object being initialized, which must have
|
|
|
|
|
/// class type.
|
|
|
|
|
///
|
|
|
|
|
/// \param ArgsPtr the arguments provided to initialize the object
|
|
|
|
|
///
|
|
|
|
|
/// \param Loc the source location where the initialization occurs
|
|
|
|
|
///
|
|
|
|
|
/// \param Range the source range that covers the entire initialization
|
|
|
|
|
///
|
|
|
|
|
/// \param InitEntity the name of the entity being initialized, if known
|
|
|
|
|
///
|
|
|
|
|
/// \param Kind the type of initialization being performed
|
|
|
|
|
///
|
|
|
|
|
/// \param ConvertedArgs a vector that will be filled in with the
|
|
|
|
|
/// appropriately-converted arguments to the constructor (if initialization
|
|
|
|
|
/// succeeded).
|
|
|
|
|
///
|
|
|
|
|
/// \returns the constructor used to initialize the object, if successful.
|
|
|
|
|
/// Otherwise, emits a diagnostic and returns NULL.
|
2008-11-04 04:45:27 +08:00
|
|
|
|
CXXConstructorDecl *
|
2008-11-05 23:29:30 +08:00
|
|
|
|
Sema::PerformInitializationByConstructor(QualType ClassType,
|
2009-09-10 07:08:42 +08:00
|
|
|
|
MultiExprArg ArgsPtr,
|
2008-11-05 23:29:30 +08:00
|
|
|
|
SourceLocation Loc, SourceRange Range,
|
2008-11-24 13:29:24 +08:00
|
|
|
|
DeclarationName InitEntity,
|
2009-09-10 07:08:42 +08:00
|
|
|
|
InitializationKind Kind,
|
|
|
|
|
ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs) {
|
2009-07-30 05:53:49 +08:00
|
|
|
|
const RecordType *ClassRec = ClassType->getAs<RecordType>();
|
2008-11-04 04:45:27 +08:00
|
|
|
|
assert(ClassRec && "Can only initialize a class type here");
|
2009-09-10 07:08:42 +08:00
|
|
|
|
Expr **Args = (Expr **)ArgsPtr.get();
|
|
|
|
|
unsigned NumArgs = ArgsPtr.size();
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// C++ [dcl.init]p14:
|
2008-11-04 04:45:27 +08:00
|
|
|
|
// If the initialization is direct-initialization, or if it is
|
|
|
|
|
// copy-initialization where the cv-unqualified version of the
|
|
|
|
|
// source type is the same class as, or a derived class of, the
|
|
|
|
|
// class of the destination, constructors are considered. The
|
|
|
|
|
// applicable constructors are enumerated (13.3.1.3), and the
|
|
|
|
|
// best one is chosen through overload resolution (13.3). The
|
|
|
|
|
// constructor so selected is called to initialize the object,
|
|
|
|
|
// with the initializer expression(s) as its argument(s). If no
|
|
|
|
|
// constructor applies, or the overload resolution is ambiguous,
|
|
|
|
|
// the initialization is ill-formed.
|
|
|
|
|
const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl());
|
|
|
|
|
OverloadCandidateSet CandidateSet;
|
2008-11-05 23:29:30 +08:00
|
|
|
|
|
|
|
|
|
// Add constructors to the overload set.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
DeclarationName ConstructorName
|
2008-12-16 05:24:18 +08:00
|
|
|
|
= Context.DeclarationNames.getCXXConstructorName(
|
|
|
|
|
Context.getCanonicalType(ClassType.getUnqualifiedType()));
|
2008-12-23 08:26:44 +08:00
|
|
|
|
DeclContext::lookup_const_iterator Con, ConEnd;
|
2009-06-30 10:36:12 +08:00
|
|
|
|
for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName);
|
2008-12-23 08:26:44 +08:00
|
|
|
|
Con != ConEnd; ++Con) {
|
2009-08-22 02:42:58 +08:00
|
|
|
|
// Find the constructor (which may be a template).
|
|
|
|
|
CXXConstructorDecl *Constructor = 0;
|
|
|
|
|
FunctionTemplateDecl *ConstructorTmpl= dyn_cast<FunctionTemplateDecl>(*Con);
|
|
|
|
|
if (ConstructorTmpl)
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Constructor
|
2009-08-22 02:42:58 +08:00
|
|
|
|
= cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
|
|
|
|
|
else
|
|
|
|
|
Constructor = cast<CXXConstructorDecl>(*Con);
|
|
|
|
|
|
2008-11-05 23:29:30 +08:00
|
|
|
|
if ((Kind == IK_Direct) ||
|
2009-09-09 23:08:12 +08:00
|
|
|
|
(Kind == IK_Copy &&
|
2009-08-29 00:57:08 +08:00
|
|
|
|
Constructor->isConvertingConstructor(/*AllowExplicit=*/false)) ||
|
2009-08-22 02:42:58 +08:00
|
|
|
|
(Kind == IK_Default && Constructor->isDefaultConstructor())) {
|
|
|
|
|
if (ConstructorTmpl)
|
2009-09-09 23:08:12 +08:00
|
|
|
|
AddTemplateOverloadCandidate(ConstructorTmpl, false, 0, 0,
|
2009-08-22 02:42:58 +08:00
|
|
|
|
Args, NumArgs, CandidateSet);
|
|
|
|
|
else
|
|
|
|
|
AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet);
|
|
|
|
|
}
|
2008-11-05 23:29:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-12-16 05:24:18 +08:00
|
|
|
|
// FIXME: When we decide not to synthesize the implicitly-declared
|
|
|
|
|
// constructors, we'll need to make them appear here.
|
|
|
|
|
|
2008-11-04 04:45:27 +08:00
|
|
|
|
OverloadCandidateSet::iterator Best;
|
2009-06-20 07:52:42 +08:00
|
|
|
|
switch (BestViableFunction(CandidateSet, Loc, Best)) {
|
2008-11-04 04:45:27 +08:00
|
|
|
|
case OR_Success:
|
2009-09-10 07:08:42 +08:00
|
|
|
|
// We found a constructor. Break out so that we can convert the arguments
|
|
|
|
|
// appropriately.
|
|
|
|
|
break;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2008-11-04 04:45:27 +08:00
|
|
|
|
case OR_No_Viable_Function:
|
2009-02-03 01:43:21 +08:00
|
|
|
|
if (InitEntity)
|
|
|
|
|
Diag(Loc, diag::err_ovl_no_viable_function_in_init)
|
2009-02-17 15:29:20 +08:00
|
|
|
|
<< InitEntity << Range;
|
2009-02-03 01:43:21 +08:00
|
|
|
|
else
|
|
|
|
|
Diag(Loc, diag::err_ovl_no_viable_function_in_init)
|
2009-02-17 15:29:20 +08:00
|
|
|
|
<< ClassType << Range;
|
2008-11-22 21:44:36 +08:00
|
|
|
|
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
|
2008-11-04 04:45:27 +08:00
|
|
|
|
return 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2008-11-04 04:45:27 +08:00
|
|
|
|
case OR_Ambiguous:
|
2009-02-03 01:43:21 +08:00
|
|
|
|
if (InitEntity)
|
|
|
|
|
Diag(Loc, diag::err_ovl_ambiguous_init) << InitEntity << Range;
|
|
|
|
|
else
|
|
|
|
|
Diag(Loc, diag::err_ovl_ambiguous_init) << ClassType << Range;
|
2008-11-04 04:45:27 +08:00
|
|
|
|
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
|
|
|
|
|
return 0;
|
2009-02-19 05:56:37 +08:00
|
|
|
|
|
|
|
|
|
case OR_Deleted:
|
|
|
|
|
if (InitEntity)
|
|
|
|
|
Diag(Loc, diag::err_ovl_deleted_init)
|
|
|
|
|
<< Best->Function->isDeleted()
|
|
|
|
|
<< InitEntity << Range;
|
|
|
|
|
else
|
|
|
|
|
Diag(Loc, diag::err_ovl_deleted_init)
|
|
|
|
|
<< Best->Function->isDeleted()
|
|
|
|
|
<< InitEntity << Range;
|
|
|
|
|
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
|
|
|
|
|
return 0;
|
2008-11-04 04:45:27 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-09-10 07:08:42 +08:00
|
|
|
|
// Convert the arguments, fill in default arguments, etc.
|
|
|
|
|
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
|
|
|
|
|
if (CompleteConstructorCall(Constructor, move(ArgsPtr), Loc, ConvertedArgs))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return Constructor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// \brief Given a constructor and the set of arguments provided for the
|
|
|
|
|
/// constructor, convert the arguments and add any required default arguments
|
|
|
|
|
/// to form a proper call to this constructor.
|
|
|
|
|
///
|
|
|
|
|
/// \returns true if an error occurred, false otherwise.
|
|
|
|
|
bool
|
|
|
|
|
Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
|
|
|
|
|
MultiExprArg ArgsPtr,
|
|
|
|
|
SourceLocation Loc,
|
|
|
|
|
ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs) {
|
|
|
|
|
// FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall.
|
|
|
|
|
unsigned NumArgs = ArgsPtr.size();
|
|
|
|
|
Expr **Args = (Expr **)ArgsPtr.get();
|
|
|
|
|
|
|
|
|
|
const FunctionProtoType *Proto
|
|
|
|
|
= Constructor->getType()->getAs<FunctionProtoType>();
|
|
|
|
|
assert(Proto && "Constructor without a prototype?");
|
|
|
|
|
unsigned NumArgsInProto = Proto->getNumArgs();
|
|
|
|
|
unsigned NumArgsToCheck = NumArgs;
|
|
|
|
|
|
|
|
|
|
// If too few arguments are available, we'll fill in the rest with defaults.
|
|
|
|
|
if (NumArgs < NumArgsInProto) {
|
|
|
|
|
NumArgsToCheck = NumArgsInProto;
|
|
|
|
|
ConvertedArgs.reserve(NumArgsInProto);
|
|
|
|
|
} else {
|
|
|
|
|
ConvertedArgs.reserve(NumArgs);
|
|
|
|
|
if (NumArgs > NumArgsInProto)
|
|
|
|
|
NumArgsToCheck = NumArgsInProto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Convert arguments
|
|
|
|
|
for (unsigned i = 0; i != NumArgsToCheck; i++) {
|
|
|
|
|
QualType ProtoArgType = Proto->getArgType(i);
|
|
|
|
|
|
|
|
|
|
Expr *Arg;
|
|
|
|
|
if (i < NumArgs) {
|
|
|
|
|
Arg = Args[i];
|
|
|
|
|
|
|
|
|
|
// Pass the argument.
|
|
|
|
|
if (PerformCopyInitialization(Arg, ProtoArgType, "passing"))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
Args[i] = 0;
|
|
|
|
|
} else {
|
|
|
|
|
ParmVarDecl *Param = Constructor->getParamDecl(i);
|
|
|
|
|
|
|
|
|
|
OwningExprResult DefArg = BuildCXXDefaultArgExpr(Loc, Constructor, Param);
|
|
|
|
|
if (DefArg.isInvalid())
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
Arg = DefArg.takeAs<Expr>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ConvertedArgs.push_back(Arg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If this is a variadic call, handle args passed through "...".
|
|
|
|
|
if (Proto->isVariadic()) {
|
|
|
|
|
// Promote the arguments (C99 6.5.2.2p7).
|
|
|
|
|
for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
|
|
|
|
|
Expr *Arg = Args[i];
|
|
|
|
|
if (DefaultVariadicArgumentPromotion(Arg, VariadicConstructor))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
ConvertedArgs.push_back(Arg);
|
|
|
|
|
Args[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
2008-11-04 04:45:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-10-29 08:13:59 +08:00
|
|
|
|
/// CompareReferenceRelationship - Compare the two types T1 and T2 to
|
|
|
|
|
/// determine whether they are reference-related,
|
|
|
|
|
/// reference-compatible, reference-compatible with added
|
|
|
|
|
/// qualification, or incompatible, for use in C++ initialization by
|
|
|
|
|
/// reference (C++ [dcl.ref.init]p4). Neither type can be a reference
|
|
|
|
|
/// type, and the first type (T1) is the pointee type of the reference
|
|
|
|
|
/// type being initialized.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Sema::ReferenceCompareResult
|
|
|
|
|
Sema::CompareReferenceRelationship(QualType T1, QualType T2,
|
2008-10-29 10:00:59 +08:00
|
|
|
|
bool& DerivedToBase) {
|
2009-03-17 07:22:08 +08:00
|
|
|
|
assert(!T1->isReferenceType() &&
|
|
|
|
|
"T1 must be the pointee type of the reference type");
|
2008-10-29 08:13:59 +08:00
|
|
|
|
assert(!T2->isReferenceType() && "T2 cannot be a reference type");
|
|
|
|
|
|
|
|
|
|
T1 = Context.getCanonicalType(T1);
|
|
|
|
|
T2 = Context.getCanonicalType(T2);
|
|
|
|
|
QualType UnqualT1 = T1.getUnqualifiedType();
|
|
|
|
|
QualType UnqualT2 = T2.getUnqualifiedType();
|
|
|
|
|
|
|
|
|
|
// C++ [dcl.init.ref]p4:
|
2009-08-06 03:21:58 +08:00
|
|
|
|
// Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// reference-related to "cv2 T2" if T1 is the same type as T2, or
|
2008-10-29 08:13:59 +08:00
|
|
|
|
// T1 is a base class of T2.
|
2008-10-29 10:00:59 +08:00
|
|
|
|
if (UnqualT1 == UnqualT2)
|
|
|
|
|
DerivedToBase = false;
|
|
|
|
|
else if (IsDerivedFrom(UnqualT2, UnqualT1))
|
|
|
|
|
DerivedToBase = true;
|
|
|
|
|
else
|
2008-10-29 08:13:59 +08:00
|
|
|
|
return Ref_Incompatible;
|
|
|
|
|
|
|
|
|
|
// At this point, we know that T1 and T2 are reference-related (at
|
|
|
|
|
// least).
|
|
|
|
|
|
|
|
|
|
// C++ [dcl.init.ref]p4:
|
2009-08-06 03:21:58 +08:00
|
|
|
|
// "cv1 T1" is reference-compatible with "cv2 T2" if T1 is
|
2008-10-29 08:13:59 +08:00
|
|
|
|
// reference-related to T2 and cv1 is the same cv-qualification
|
|
|
|
|
// as, or greater cv-qualification than, cv2. For purposes of
|
|
|
|
|
// overload resolution, cases for which cv1 is greater
|
|
|
|
|
// cv-qualification than cv2 are identified as
|
|
|
|
|
// reference-compatible with added qualification (see 13.3.3.2).
|
|
|
|
|
if (T1.getCVRQualifiers() == T2.getCVRQualifiers())
|
|
|
|
|
return Ref_Compatible;
|
|
|
|
|
else if (T1.isMoreQualifiedThan(T2))
|
|
|
|
|
return Ref_Compatible_With_Added_Qualification;
|
|
|
|
|
else
|
|
|
|
|
return Ref_Related;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// CheckReferenceInit - Check the initialization of a reference
|
|
|
|
|
/// variable with the given initializer (C++ [dcl.init.ref]). Init is
|
|
|
|
|
/// the initializer (either a simple initializer or an initializer
|
2008-10-30 07:31:03 +08:00
|
|
|
|
/// list), and DeclType is the type of the declaration. When ICS is
|
|
|
|
|
/// non-null, this routine will compute the implicit conversion
|
|
|
|
|
/// sequence according to C++ [over.ics.ref] and will not produce any
|
|
|
|
|
/// diagnostics; when ICS is null, it will emit diagnostics when any
|
|
|
|
|
/// errors are found. Either way, a return value of true indicates
|
|
|
|
|
/// that there was a failure, a return value of false indicates that
|
|
|
|
|
/// the reference initialization succeeded.
|
2008-11-04 03:09:14 +08:00
|
|
|
|
///
|
|
|
|
|
/// When @p SuppressUserConversions, user-defined conversions are
|
|
|
|
|
/// suppressed.
|
2009-01-14 23:45:31 +08:00
|
|
|
|
/// When @p AllowExplicit, we also permit explicit user-defined
|
|
|
|
|
/// conversion functions.
|
2009-04-13 01:16:29 +08:00
|
|
|
|
/// When @p ForceRValue, we unconditionally treat the initializer as an rvalue.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
bool
|
2009-04-17 01:51:27 +08:00
|
|
|
|
Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
|
2009-01-14 23:45:31 +08:00
|
|
|
|
bool SuppressUserConversions,
|
2009-08-28 01:30:43 +08:00
|
|
|
|
bool AllowExplicit, bool ForceRValue,
|
|
|
|
|
ImplicitConversionSequence *ICS) {
|
2008-10-29 08:13:59 +08:00
|
|
|
|
assert(DeclType->isReferenceType() && "Reference init needs a reference");
|
|
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
|
QualType T1 = DeclType->getAs<ReferenceType>()->getPointeeType();
|
2008-10-29 08:13:59 +08:00
|
|
|
|
QualType T2 = Init->getType();
|
|
|
|
|
|
2008-11-11 04:40:00 +08:00
|
|
|
|
// If the initializer is the address of an overloaded function, try
|
|
|
|
|
// to resolve the overloaded function. If all goes well, T2 is the
|
|
|
|
|
// type of the resulting function.
|
2009-03-14 02:40:31 +08:00
|
|
|
|
if (Context.getCanonicalType(T2) == Context.OverloadTy) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Init, DeclType,
|
2008-11-11 04:40:00 +08:00
|
|
|
|
ICS != 0);
|
|
|
|
|
if (Fn) {
|
|
|
|
|
// Since we're performing this reference-initialization for
|
|
|
|
|
// real, update the initializer with the resulting function.
|
2009-02-19 05:56:37 +08:00
|
|
|
|
if (!ICS) {
|
|
|
|
|
if (DiagnoseUseOfDecl(Fn, Init->getSourceRange().getBegin()))
|
|
|
|
|
return true;
|
|
|
|
|
|
2008-11-11 04:40:00 +08:00
|
|
|
|
FixOverloadedFunctionReference(Init, Fn);
|
2009-02-19 05:56:37 +08:00
|
|
|
|
}
|
2008-11-11 04:40:00 +08:00
|
|
|
|
|
|
|
|
|
T2 = Fn->getType();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-29 10:00:59 +08:00
|
|
|
|
// Compute some basic properties of the types and the initializer.
|
2009-03-17 07:22:08 +08:00
|
|
|
|
bool isRValRef = DeclType->isRValueReferenceType();
|
2008-10-29 10:00:59 +08:00
|
|
|
|
bool DerivedToBase = false;
|
2009-04-13 01:16:29 +08:00
|
|
|
|
Expr::isLvalueResult InitLvalue = ForceRValue ? Expr::LV_InvalidExpression :
|
|
|
|
|
Init->isLvalue(Context);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
ReferenceCompareResult RefRelationship
|
2008-10-29 10:00:59 +08:00
|
|
|
|
= CompareReferenceRelationship(T1, T2, DerivedToBase);
|
|
|
|
|
|
|
|
|
|
// Most paths end in a failed conversion.
|
|
|
|
|
if (ICS)
|
|
|
|
|
ICS->ConversionKind = ImplicitConversionSequence::BadConversion;
|
2008-10-29 08:13:59 +08:00
|
|
|
|
|
|
|
|
|
// C++ [dcl.init.ref]p5:
|
2009-08-06 03:21:58 +08:00
|
|
|
|
// A reference to type "cv1 T1" is initialized by an expression
|
|
|
|
|
// of type "cv2 T2" as follows:
|
2008-10-29 08:13:59 +08:00
|
|
|
|
|
|
|
|
|
// -- If the initializer expression
|
|
|
|
|
|
2009-03-29 23:27:50 +08:00
|
|
|
|
// Rvalue references cannot bind to lvalues (N2812).
|
|
|
|
|
// There is absolutely no situation where they can. In particular, note that
|
|
|
|
|
// this is ill-formed, even if B has a user-defined conversion to A&&:
|
|
|
|
|
// B b;
|
|
|
|
|
// A&& r = b;
|
|
|
|
|
if (isRValRef && InitLvalue == Expr::LV_Valid) {
|
|
|
|
|
if (!ICS)
|
|
|
|
|
Diag(Init->getSourceRange().getBegin(), diag::err_lvalue_to_rvalue_ref)
|
|
|
|
|
<< Init->getSourceRange();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-29 08:13:59 +08:00
|
|
|
|
bool BindsDirectly = false;
|
2009-08-06 03:21:58 +08:00
|
|
|
|
// -- is an lvalue (but is not a bit-field), and "cv1 T1" is
|
|
|
|
|
// reference-compatible with "cv2 T2," or
|
2008-10-29 10:00:59 +08:00
|
|
|
|
//
|
|
|
|
|
// Note that the bit-field check is skipped if we are just computing
|
|
|
|
|
// the implicit conversion sequence (C++ [over.best.ics]p2).
|
2009-05-02 10:18:30 +08:00
|
|
|
|
if (InitLvalue == Expr::LV_Valid && (ICS || !Init->getBitField()) &&
|
2008-10-29 10:00:59 +08:00
|
|
|
|
RefRelationship >= Ref_Compatible_With_Added_Qualification) {
|
2008-10-29 08:13:59 +08:00
|
|
|
|
BindsDirectly = true;
|
|
|
|
|
|
2008-10-29 10:00:59 +08:00
|
|
|
|
if (ICS) {
|
|
|
|
|
// C++ [over.ics.ref]p1:
|
|
|
|
|
// When a parameter of reference type binds directly (8.5.3)
|
|
|
|
|
// to an argument expression, the implicit conversion sequence
|
|
|
|
|
// is the identity conversion, unless the argument expression
|
|
|
|
|
// has a type that is a derived class of the parameter type,
|
|
|
|
|
// in which case the implicit conversion sequence is a
|
|
|
|
|
// derived-to-base Conversion (13.3.3.1).
|
|
|
|
|
ICS->ConversionKind = ImplicitConversionSequence::StandardConversion;
|
|
|
|
|
ICS->Standard.First = ICK_Identity;
|
|
|
|
|
ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
|
|
|
|
|
ICS->Standard.Third = ICK_Identity;
|
|
|
|
|
ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
|
|
|
|
|
ICS->Standard.ToTypePtr = T1.getAsOpaquePtr();
|
2008-10-29 22:50:44 +08:00
|
|
|
|
ICS->Standard.ReferenceBinding = true;
|
|
|
|
|
ICS->Standard.DirectBinding = true;
|
2009-03-29 23:27:50 +08:00
|
|
|
|
ICS->Standard.RRefBinding = false;
|
2009-04-18 00:30:52 +08:00
|
|
|
|
ICS->Standard.CopyConstructor = 0;
|
2008-10-29 10:00:59 +08:00
|
|
|
|
|
|
|
|
|
// Nothing more to do: the inaccessibility/ambiguity check for
|
|
|
|
|
// derived-to-base conversions is suppressed when we're
|
|
|
|
|
// computing the implicit conversion sequence (C++
|
|
|
|
|
// [over.best.ics]p2).
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
// Perform the conversion.
|
2009-09-10 07:08:42 +08:00
|
|
|
|
CastExpr::CastKind CK = CastExpr::CK_NoOp;
|
|
|
|
|
if (DerivedToBase)
|
|
|
|
|
CK = CastExpr::CK_DerivedToBase;
|
|
|
|
|
ImpCastExprToType(Init, T1, CK, /*isLvalue=*/true);
|
2008-10-29 08:13:59 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -- has a class type (i.e., T2 is a class type) and can be
|
2009-08-06 03:21:58 +08:00
|
|
|
|
// implicitly converted to an lvalue of type "cv3 T3,"
|
|
|
|
|
// where "cv1 T1" is reference-compatible with "cv3 T3"
|
2008-10-29 08:13:59 +08:00
|
|
|
|
// 92) (this conversion is selected by enumerating the
|
|
|
|
|
// applicable conversion functions (13.3.1.6) and choosing
|
|
|
|
|
// the best one through overload resolution (13.3)),
|
2009-08-24 23:23:48 +08:00
|
|
|
|
if (!isRValRef && !SuppressUserConversions && T2->isRecordType() &&
|
|
|
|
|
!RequireCompleteType(SourceLocation(), T2, 0)) {
|
2008-11-11 00:14:15 +08:00
|
|
|
|
// FIXME: Look for conversions in base classes!
|
2009-09-09 23:08:12 +08:00
|
|
|
|
CXXRecordDecl *T2RecordDecl
|
2009-07-30 05:53:49 +08:00
|
|
|
|
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
|
2008-11-11 00:14:15 +08:00
|
|
|
|
|
|
|
|
|
OverloadCandidateSet CandidateSet;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
OverloadedFunctionDecl *Conversions
|
2008-11-11 00:14:15 +08:00
|
|
|
|
= T2RecordDecl->getConversionFunctions();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
for (OverloadedFunctionDecl::function_iterator Func
|
2008-11-11 00:14:15 +08:00
|
|
|
|
= Conversions->function_begin();
|
|
|
|
|
Func != Conversions->function_end(); ++Func) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
FunctionTemplateDecl *ConvTemplate
|
2009-08-22 07:19:43 +08:00
|
|
|
|
= dyn_cast<FunctionTemplateDecl>(*Func);
|
|
|
|
|
CXXConversionDecl *Conv;
|
|
|
|
|
if (ConvTemplate)
|
|
|
|
|
Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
|
|
|
|
|
else
|
|
|
|
|
Conv = cast<CXXConversionDecl>(*Func);
|
2009-03-23 05:28:55 +08:00
|
|
|
|
|
2008-11-11 00:14:15 +08:00
|
|
|
|
// If the conversion function doesn't return a reference type,
|
|
|
|
|
// it can't be considered for this conversion.
|
2009-03-17 07:22:08 +08:00
|
|
|
|
if (Conv->getConversionType()->isLValueReferenceType() &&
|
2009-08-22 07:19:43 +08:00
|
|
|
|
(AllowExplicit || !Conv->isExplicit())) {
|
|
|
|
|
if (ConvTemplate)
|
2009-09-09 23:08:12 +08:00
|
|
|
|
AddTemplateConversionCandidate(ConvTemplate, Init, DeclType,
|
2009-08-22 07:19:43 +08:00
|
|
|
|
CandidateSet);
|
|
|
|
|
else
|
|
|
|
|
AddConversionCandidate(Conv, Init, DeclType, CandidateSet);
|
|
|
|
|
}
|
2008-11-11 00:14:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OverloadCandidateSet::iterator Best;
|
2009-06-20 07:52:42 +08:00
|
|
|
|
switch (BestViableFunction(CandidateSet, Init->getLocStart(), Best)) {
|
2008-11-11 00:14:15 +08:00
|
|
|
|
case OR_Success:
|
|
|
|
|
// This is a direct binding.
|
|
|
|
|
BindsDirectly = true;
|
|
|
|
|
|
|
|
|
|
if (ICS) {
|
|
|
|
|
// C++ [over.ics.ref]p1:
|
|
|
|
|
//
|
|
|
|
|
// [...] If the parameter binds directly to the result of
|
|
|
|
|
// applying a conversion function to the argument
|
|
|
|
|
// expression, the implicit conversion sequence is a
|
|
|
|
|
// user-defined conversion sequence (13.3.3.1.2), with the
|
|
|
|
|
// second standard conversion sequence either an identity
|
|
|
|
|
// conversion or, if the conversion function returns an
|
|
|
|
|
// entity of a type that is a derived class of the parameter
|
|
|
|
|
// type, a derived-to-base Conversion.
|
|
|
|
|
ICS->ConversionKind = ImplicitConversionSequence::UserDefinedConversion;
|
|
|
|
|
ICS->UserDefined.Before = Best->Conversions[0].Standard;
|
|
|
|
|
ICS->UserDefined.After = Best->FinalConversion;
|
|
|
|
|
ICS->UserDefined.ConversionFunction = Best->Function;
|
|
|
|
|
assert(ICS->UserDefined.After.ReferenceBinding &&
|
|
|
|
|
ICS->UserDefined.After.DirectBinding &&
|
|
|
|
|
"Expected a direct reference binding!");
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
// Perform the conversion.
|
2009-05-16 15:39:55 +08:00
|
|
|
|
// FIXME: Binding to a subobject of the lvalue is going to require more
|
|
|
|
|
// AST annotation than this.
|
2009-07-31 09:23:52 +08:00
|
|
|
|
ImpCastExprToType(Init, T1, CastExpr::CK_Unknown, /*isLvalue=*/true);
|
2008-11-11 00:14:15 +08:00
|
|
|
|
}
|
|
|
|
|
break;
|
2008-10-29 08:13:59 +08:00
|
|
|
|
|
2008-11-11 00:14:15 +08:00
|
|
|
|
case OR_Ambiguous:
|
|
|
|
|
assert(false && "Ambiguous reference binding conversions not implemented.");
|
|
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2008-11-11 00:14:15 +08:00
|
|
|
|
case OR_No_Viable_Function:
|
2009-02-19 05:56:37 +08:00
|
|
|
|
case OR_Deleted:
|
|
|
|
|
// There was no suitable conversion, or we found a deleted
|
|
|
|
|
// conversion; continue with other checks.
|
2008-11-11 00:14:15 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2008-10-29 08:13:59 +08:00
|
|
|
|
if (BindsDirectly) {
|
|
|
|
|
// C++ [dcl.init.ref]p4:
|
|
|
|
|
// [...] In all cases where the reference-related or
|
|
|
|
|
// reference-compatible relationship of two types is used to
|
|
|
|
|
// establish the validity of a reference binding, and T1 is a
|
|
|
|
|
// base class of T2, a program that necessitates such a binding
|
|
|
|
|
// is ill-formed if T1 is an inaccessible (clause 11) or
|
|
|
|
|
// ambiguous (10.2) base class of T2.
|
|
|
|
|
//
|
|
|
|
|
// Note that we only check this condition when we're allowed to
|
|
|
|
|
// complain about errors, because we should not be checking for
|
|
|
|
|
// ambiguity (or inaccessibility) unless the reference binding
|
|
|
|
|
// actually happens.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (DerivedToBase)
|
|
|
|
|
return CheckDerivedToBaseConversion(T2, T1,
|
2008-10-29 10:00:59 +08:00
|
|
|
|
Init->getSourceRange().getBegin(),
|
|
|
|
|
Init->getSourceRange());
|
|
|
|
|
else
|
|
|
|
|
return false;
|
2008-10-29 08:13:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -- Otherwise, the reference shall be to a non-volatile const
|
2009-03-29 23:27:50 +08:00
|
|
|
|
// type (i.e., cv1 shall be const), or the reference shall be an
|
|
|
|
|
// rvalue reference and the initializer expression shall be an rvalue.
|
2009-03-17 07:22:08 +08:00
|
|
|
|
if (!isRValRef && T1.getCVRQualifiers() != QualType::Const) {
|
2008-10-29 10:00:59 +08:00
|
|
|
|
if (!ICS)
|
2008-10-29 08:13:59 +08:00
|
|
|
|
Diag(Init->getSourceRange().getBegin(),
|
2008-11-19 06:52:51 +08:00
|
|
|
|
diag::err_not_reference_to_const_init)
|
2008-11-24 14:25:27 +08:00
|
|
|
|
<< T1 << (InitLvalue != Expr::LV_Valid? "temporary" : "value")
|
|
|
|
|
<< T2 << Init->getSourceRange();
|
2008-10-29 08:13:59 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -- If the initializer expression is an rvalue, with T2 a
|
2009-08-06 03:21:58 +08:00
|
|
|
|
// class type, and "cv1 T1" is reference-compatible with
|
|
|
|
|
// "cv2 T2," the reference is bound in one of the
|
2008-10-29 08:13:59 +08:00
|
|
|
|
// following ways (the choice is implementation-defined):
|
|
|
|
|
//
|
|
|
|
|
// -- The reference is bound to the object represented by
|
|
|
|
|
// the rvalue (see 3.10) or to a sub-object within that
|
|
|
|
|
// object.
|
|
|
|
|
//
|
2009-08-06 03:21:58 +08:00
|
|
|
|
// -- A temporary of type "cv1 T2" [sic] is created, and
|
2008-10-29 08:13:59 +08:00
|
|
|
|
// a constructor is called to copy the entire rvalue
|
|
|
|
|
// object into the temporary. The reference is bound to
|
|
|
|
|
// the temporary or to a sub-object within the
|
|
|
|
|
// temporary.
|
|
|
|
|
//
|
|
|
|
|
// The constructor that would be used to make the copy
|
|
|
|
|
// shall be callable whether or not the copy is actually
|
|
|
|
|
// done.
|
|
|
|
|
//
|
2009-03-29 23:27:50 +08:00
|
|
|
|
// Note that C++0x [dcl.init.ref]p5 takes away this implementation
|
2008-10-29 08:13:59 +08:00
|
|
|
|
// freedom, so we will always take the first option and never build
|
|
|
|
|
// a temporary in this case. FIXME: We will, however, have to check
|
|
|
|
|
// for the presence of a copy constructor in C++98/03 mode.
|
|
|
|
|
if (InitLvalue != Expr::LV_Valid && T2->isRecordType() &&
|
2008-10-29 10:00:59 +08:00
|
|
|
|
RefRelationship >= Ref_Compatible_With_Added_Qualification) {
|
|
|
|
|
if (ICS) {
|
|
|
|
|
ICS->ConversionKind = ImplicitConversionSequence::StandardConversion;
|
|
|
|
|
ICS->Standard.First = ICK_Identity;
|
|
|
|
|
ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
|
|
|
|
|
ICS->Standard.Third = ICK_Identity;
|
|
|
|
|
ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
|
|
|
|
|
ICS->Standard.ToTypePtr = T1.getAsOpaquePtr();
|
2008-10-29 22:50:44 +08:00
|
|
|
|
ICS->Standard.ReferenceBinding = true;
|
2009-03-29 23:27:50 +08:00
|
|
|
|
ICS->Standard.DirectBinding = false;
|
|
|
|
|
ICS->Standard.RRefBinding = isRValRef;
|
2009-04-18 00:30:52 +08:00
|
|
|
|
ICS->Standard.CopyConstructor = 0;
|
2008-10-29 10:00:59 +08:00
|
|
|
|
} else {
|
2009-09-10 07:08:42 +08:00
|
|
|
|
CastExpr::CastKind CK = CastExpr::CK_NoOp;
|
|
|
|
|
if (DerivedToBase)
|
|
|
|
|
CK = CastExpr::CK_DerivedToBase;
|
|
|
|
|
ImpCastExprToType(Init, T1, CK, /*isLvalue=*/false);
|
2008-10-29 08:13:59 +08:00
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-06 03:21:58 +08:00
|
|
|
|
// -- Otherwise, a temporary of type "cv1 T1" is created and
|
2008-10-29 08:13:59 +08:00
|
|
|
|
// initialized from the initializer expression using the
|
|
|
|
|
// rules for a non-reference copy initialization (8.5). The
|
|
|
|
|
// reference is then bound to the temporary. If T1 is
|
|
|
|
|
// reference-related to T2, cv1 must be the same
|
|
|
|
|
// cv-qualification as, or greater cv-qualification than,
|
|
|
|
|
// cv2; otherwise, the program is ill-formed.
|
|
|
|
|
if (RefRelationship == Ref_Related) {
|
|
|
|
|
// If cv1 == cv2 or cv1 is a greater cv-qualified than cv2, then
|
|
|
|
|
// we would be reference-compatible or reference-compatible with
|
|
|
|
|
// added qualification. But that wasn't the case, so the reference
|
|
|
|
|
// initialization fails.
|
2008-10-29 10:00:59 +08:00
|
|
|
|
if (!ICS)
|
2008-10-29 08:13:59 +08:00
|
|
|
|
Diag(Init->getSourceRange().getBegin(),
|
2008-11-19 06:52:51 +08:00
|
|
|
|
diag::err_reference_init_drops_quals)
|
2008-11-24 14:25:27 +08:00
|
|
|
|
<< T1 << (InitLvalue != Expr::LV_Valid? "temporary" : "value")
|
|
|
|
|
<< T2 << Init->getSourceRange();
|
2008-10-29 08:13:59 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2009-01-31 07:27:23 +08:00
|
|
|
|
// If at least one of the types is a class type, the types are not
|
|
|
|
|
// related, and we aren't allowed any user conversions, the
|
|
|
|
|
// reference binding fails. This case is important for breaking
|
|
|
|
|
// recursion, since TryImplicitConversion below will attempt to
|
|
|
|
|
// create a temporary through the use of a copy constructor.
|
|
|
|
|
if (SuppressUserConversions && RefRelationship == Ref_Incompatible &&
|
|
|
|
|
(T1->isRecordType() || T2->isRecordType())) {
|
|
|
|
|
if (!ICS)
|
|
|
|
|
Diag(Init->getSourceRange().getBegin(),
|
|
|
|
|
diag::err_typecheck_convert_incompatible)
|
|
|
|
|
<< DeclType << Init->getType() << "initializing" << Init->getSourceRange();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-29 08:13:59 +08:00
|
|
|
|
// Actually try to convert the initializer to T1.
|
2008-10-29 10:00:59 +08:00
|
|
|
|
if (ICS) {
|
2009-03-29 23:27:50 +08:00
|
|
|
|
// C++ [over.ics.ref]p2:
|
2009-09-09 23:08:12 +08:00
|
|
|
|
//
|
2009-03-29 23:27:50 +08:00
|
|
|
|
// When a parameter of reference type is not bound directly to
|
|
|
|
|
// an argument expression, the conversion sequence is the one
|
|
|
|
|
// required to convert the argument expression to the
|
|
|
|
|
// underlying type of the reference according to
|
|
|
|
|
// 13.3.3.1. Conceptually, this conversion sequence corresponds
|
|
|
|
|
// to copy-initializing a temporary of the underlying type with
|
|
|
|
|
// the argument expression. Any difference in top-level
|
|
|
|
|
// cv-qualification is subsumed by the initialization itself
|
|
|
|
|
// and does not constitute a conversion.
|
2009-08-28 01:24:15 +08:00
|
|
|
|
*ICS = TryImplicitConversion(Init, T1, SuppressUserConversions,
|
|
|
|
|
/*AllowExplicit=*/false,
|
2009-08-28 23:33:32 +08:00
|
|
|
|
/*ForceRValue=*/false,
|
|
|
|
|
/*InOverloadResolution=*/false);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-29 23:27:50 +08:00
|
|
|
|
// Of course, that's still a reference binding.
|
|
|
|
|
if (ICS->ConversionKind == ImplicitConversionSequence::StandardConversion) {
|
|
|
|
|
ICS->Standard.ReferenceBinding = true;
|
|
|
|
|
ICS->Standard.RRefBinding = isRValRef;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
} else if (ICS->ConversionKind ==
|
2009-03-29 23:27:50 +08:00
|
|
|
|
ImplicitConversionSequence::UserDefinedConversion) {
|
|
|
|
|
ICS->UserDefined.After.ReferenceBinding = true;
|
|
|
|
|
ICS->UserDefined.After.RRefBinding = isRValRef;
|
|
|
|
|
}
|
2008-10-29 10:00:59 +08:00
|
|
|
|
return ICS->ConversionKind == ImplicitConversionSequence::BadConversion;
|
|
|
|
|
} else {
|
2008-12-20 01:40:08 +08:00
|
|
|
|
return PerformImplicitConversion(Init, T1, "initializing");
|
2008-10-29 10:00:59 +08:00
|
|
|
|
}
|
2008-10-29 08:13:59 +08:00
|
|
|
|
}
|
2008-11-07 06:13:31 +08:00
|
|
|
|
|
|
|
|
|
/// CheckOverloadedOperatorDeclaration - Check whether the declaration
|
|
|
|
|
/// of this overloaded operator is well-formed. If so, returns false;
|
|
|
|
|
/// otherwise, emits appropriate diagnostics and returns true.
|
|
|
|
|
bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
|
2008-11-18 00:14:12 +08:00
|
|
|
|
assert(FnDecl && FnDecl->isOverloadedOperator() &&
|
2008-11-07 06:13:31 +08:00
|
|
|
|
"Expected an overloaded operator declaration");
|
|
|
|
|
|
|
|
|
|
OverloadedOperatorKind Op = FnDecl->getOverloadedOperator();
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// C++ [over.oper]p5:
|
2008-11-07 06:13:31 +08:00
|
|
|
|
// The allocation and deallocation functions, operator new,
|
|
|
|
|
// operator new[], operator delete and operator delete[], are
|
|
|
|
|
// described completely in 3.7.3. The attributes and restrictions
|
|
|
|
|
// found in the rest of this subclause do not apply to them unless
|
|
|
|
|
// explicitly stated in 3.7.3.
|
2009-05-16 15:39:55 +08:00
|
|
|
|
// FIXME: Write a separate routine for checking this. For now, just allow it.
|
2008-11-07 06:13:31 +08:00
|
|
|
|
if (Op == OO_New || Op == OO_Array_New ||
|
|
|
|
|
Op == OO_Delete || Op == OO_Array_Delete)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// C++ [over.oper]p6:
|
|
|
|
|
// An operator function shall either be a non-static member
|
|
|
|
|
// function or be a non-member function and have at least one
|
|
|
|
|
// parameter whose type is a class, a reference to a class, an
|
|
|
|
|
// enumeration, or a reference to an enumeration.
|
2008-11-18 00:14:12 +08:00
|
|
|
|
if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(FnDecl)) {
|
|
|
|
|
if (MethodDecl->isStatic())
|
|
|
|
|
return Diag(FnDecl->getLocation(),
|
2008-11-24 13:29:24 +08:00
|
|
|
|
diag::err_operator_overload_static) << FnDecl->getDeclName();
|
2008-11-07 06:13:31 +08:00
|
|
|
|
} else {
|
|
|
|
|
bool ClassOrEnumParam = false;
|
2008-11-18 00:14:12 +08:00
|
|
|
|
for (FunctionDecl::param_iterator Param = FnDecl->param_begin(),
|
|
|
|
|
ParamEnd = FnDecl->param_end();
|
|
|
|
|
Param != ParamEnd; ++Param) {
|
|
|
|
|
QualType ParamType = (*Param)->getType().getNonReferenceType();
|
2009-06-27 13:59:59 +08:00
|
|
|
|
if (ParamType->isDependentType() || ParamType->isRecordType() ||
|
|
|
|
|
ParamType->isEnumeralType()) {
|
2008-11-07 06:13:31 +08:00
|
|
|
|
ClassOrEnumParam = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-18 00:14:12 +08:00
|
|
|
|
if (!ClassOrEnumParam)
|
|
|
|
|
return Diag(FnDecl->getLocation(),
|
2008-11-20 14:38:18 +08:00
|
|
|
|
diag::err_operator_overload_needs_class_or_enum)
|
2008-11-24 13:29:24 +08:00
|
|
|
|
<< FnDecl->getDeclName();
|
2008-11-07 06:13:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// C++ [over.oper]p8:
|
|
|
|
|
// An operator function cannot have default arguments (8.3.6),
|
|
|
|
|
// except where explicitly stated below.
|
|
|
|
|
//
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// Only the function-call operator allows default arguments
|
2008-11-07 06:13:31 +08:00
|
|
|
|
// (C++ [over.call]p1).
|
|
|
|
|
if (Op != OO_Call) {
|
|
|
|
|
for (FunctionDecl::param_iterator Param = FnDecl->param_begin();
|
|
|
|
|
Param != FnDecl->param_end(); ++Param) {
|
2008-12-24 08:01:03 +08:00
|
|
|
|
if ((*Param)->hasUnparsedDefaultArg())
|
2009-09-09 23:08:12 +08:00
|
|
|
|
return Diag((*Param)->getLocation(),
|
2008-12-24 08:01:03 +08:00
|
|
|
|
diag::err_operator_overload_default_arg)
|
|
|
|
|
<< FnDecl->getDeclName();
|
|
|
|
|
else if (Expr *DefArg = (*Param)->getDefaultArg())
|
2008-11-18 00:14:12 +08:00
|
|
|
|
return Diag((*Param)->getLocation(),
|
2008-11-20 14:06:08 +08:00
|
|
|
|
diag::err_operator_overload_default_arg)
|
2008-11-24 13:29:24 +08:00
|
|
|
|
<< FnDecl->getDeclName() << DefArg->getSourceRange();
|
2008-11-07 06:13:31 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-10 21:38:07 +08:00
|
|
|
|
static const bool OperatorUses[NUM_OVERLOADED_OPERATORS][3] = {
|
|
|
|
|
{ false, false, false }
|
|
|
|
|
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
|
|
|
|
|
, { Unary, Binary, MemberOnly }
|
|
|
|
|
#include "clang/Basic/OperatorKinds.def"
|
|
|
|
|
};
|
2008-11-07 06:13:31 +08:00
|
|
|
|
|
2008-11-10 21:38:07 +08:00
|
|
|
|
bool CanBeUnaryOperator = OperatorUses[Op][0];
|
|
|
|
|
bool CanBeBinaryOperator = OperatorUses[Op][1];
|
|
|
|
|
bool MustBeMemberOperator = OperatorUses[Op][2];
|
2008-11-07 06:13:31 +08:00
|
|
|
|
|
|
|
|
|
// C++ [over.oper]p8:
|
|
|
|
|
// [...] Operator functions cannot have more or fewer parameters
|
|
|
|
|
// than the number required for the corresponding operator, as
|
|
|
|
|
// described in the rest of this subclause.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
unsigned NumParams = FnDecl->getNumParams()
|
2008-11-18 00:14:12 +08:00
|
|
|
|
+ (isa<CXXMethodDecl>(FnDecl)? 1 : 0);
|
2008-11-07 06:13:31 +08:00
|
|
|
|
if (Op != OO_Call &&
|
|
|
|
|
((NumParams == 1 && !CanBeUnaryOperator) ||
|
|
|
|
|
(NumParams == 2 && !CanBeBinaryOperator) ||
|
|
|
|
|
(NumParams < 1) || (NumParams > 2))) {
|
|
|
|
|
// We have the wrong number of parameters.
|
2008-11-21 15:57:12 +08:00
|
|
|
|
unsigned ErrorKind;
|
2008-11-10 21:38:07 +08:00
|
|
|
|
if (CanBeUnaryOperator && CanBeBinaryOperator) {
|
2008-11-21 15:57:12 +08:00
|
|
|
|
ErrorKind = 2; // 2 -> unary or binary.
|
2008-11-10 21:38:07 +08:00
|
|
|
|
} else if (CanBeUnaryOperator) {
|
2008-11-21 15:57:12 +08:00
|
|
|
|
ErrorKind = 0; // 0 -> unary
|
2008-11-10 21:38:07 +08:00
|
|
|
|
} else {
|
2008-11-21 15:50:02 +08:00
|
|
|
|
assert(CanBeBinaryOperator &&
|
|
|
|
|
"All non-call overloaded operators are unary or binary!");
|
2008-11-21 15:57:12 +08:00
|
|
|
|
ErrorKind = 1; // 1 -> binary
|
2008-11-10 21:38:07 +08:00
|
|
|
|
}
|
2008-11-07 06:13:31 +08:00
|
|
|
|
|
2008-11-21 15:57:12 +08:00
|
|
|
|
return Diag(FnDecl->getLocation(), diag::err_operator_overload_must_be)
|
2008-11-24 13:29:24 +08:00
|
|
|
|
<< FnDecl->getDeclName() << NumParams << ErrorKind;
|
2008-11-07 06:13:31 +08:00
|
|
|
|
}
|
2009-01-06 04:52:13 +08:00
|
|
|
|
|
2008-11-18 00:14:12 +08:00
|
|
|
|
// Overloaded operators other than operator() cannot be variadic.
|
|
|
|
|
if (Op != OO_Call &&
|
2009-02-27 07:50:07 +08:00
|
|
|
|
FnDecl->getType()->getAsFunctionProtoType()->isVariadic()) {
|
2008-11-20 14:38:18 +08:00
|
|
|
|
return Diag(FnDecl->getLocation(), diag::err_operator_overload_variadic)
|
2008-11-24 13:29:24 +08:00
|
|
|
|
<< FnDecl->getDeclName();
|
2008-11-07 06:13:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Some operators must be non-static member functions.
|
2008-11-18 00:14:12 +08:00
|
|
|
|
if (MustBeMemberOperator && !isa<CXXMethodDecl>(FnDecl)) {
|
|
|
|
|
return Diag(FnDecl->getLocation(),
|
2008-11-20 14:38:18 +08:00
|
|
|
|
diag::err_operator_overload_must_be_member)
|
2008-11-24 13:29:24 +08:00
|
|
|
|
<< FnDecl->getDeclName();
|
2008-11-07 06:13:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// C++ [over.inc]p1:
|
|
|
|
|
// The user-defined function called operator++ implements the
|
|
|
|
|
// prefix and postfix ++ operator. If this function is a member
|
|
|
|
|
// function with no parameters, or a non-member function with one
|
|
|
|
|
// parameter of class or enumeration type, it defines the prefix
|
|
|
|
|
// increment operator ++ for objects of that type. If the function
|
|
|
|
|
// is a member function with one parameter (which shall be of type
|
|
|
|
|
// int) or a non-member function with two parameters (the second
|
|
|
|
|
// of which shall be of type int), it defines the postfix
|
|
|
|
|
// increment operator ++ for objects of that type.
|
|
|
|
|
if ((Op == OO_PlusPlus || Op == OO_MinusMinus) && NumParams == 2) {
|
|
|
|
|
ParmVarDecl *LastParam = FnDecl->getParamDecl(FnDecl->getNumParams() - 1);
|
|
|
|
|
bool ParamIsInt = false;
|
|
|
|
|
if (const BuiltinType *BT = LastParam->getType()->getAsBuiltinType())
|
|
|
|
|
ParamIsInt = BT->getKind() == BuiltinType::Int;
|
|
|
|
|
|
2008-11-21 15:50:02 +08:00
|
|
|
|
if (!ParamIsInt)
|
|
|
|
|
return Diag(LastParam->getLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
|
diag::err_operator_overload_post_incdec_must_be_int)
|
2008-11-24 14:25:27 +08:00
|
|
|
|
<< LastParam->getType() << (Op == OO_MinusMinus);
|
2008-11-07 06:13:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-01-06 04:52:13 +08:00
|
|
|
|
// Notify the class if it got an assignment operator.
|
|
|
|
|
if (Op == OO_Equal) {
|
|
|
|
|
// Would have returned earlier otherwise.
|
|
|
|
|
assert(isa<CXXMethodDecl>(FnDecl) &&
|
|
|
|
|
"Overloaded = not member, but not filtered.");
|
|
|
|
|
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
|
2009-08-14 05:09:41 +08:00
|
|
|
|
Method->setCopyAssignment(true);
|
2009-01-06 04:52:13 +08:00
|
|
|
|
Method->getParent()->addedAssignmentOperator(Context, Method);
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-18 00:14:12 +08:00
|
|
|
|
return false;
|
2008-11-07 06:13:31 +08:00
|
|
|
|
}
|
2008-12-17 15:09:26 +08:00
|
|
|
|
|
2009-01-06 03:45:36 +08:00
|
|
|
|
/// ActOnStartLinkageSpecification - Parsed the beginning of a C++
|
|
|
|
|
/// linkage specification, including the language and (if present)
|
|
|
|
|
/// the '{'. ExternLoc is the location of the 'extern', LangLoc is
|
|
|
|
|
/// the location of the language string literal, which is provided
|
|
|
|
|
/// by Lang/StrSize. LBraceLoc, if valid, provides the location of
|
|
|
|
|
/// the '{' brace. Otherwise, this linkage specification does not
|
|
|
|
|
/// have any braces.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
Sema::DeclPtrTy Sema::ActOnStartLinkageSpecification(Scope *S,
|
|
|
|
|
SourceLocation ExternLoc,
|
|
|
|
|
SourceLocation LangLoc,
|
|
|
|
|
const char *Lang,
|
|
|
|
|
unsigned StrSize,
|
|
|
|
|
SourceLocation LBraceLoc) {
|
2008-12-17 15:13:27 +08:00
|
|
|
|
LinkageSpecDecl::LanguageIDs Language;
|
|
|
|
|
if (strncmp(Lang, "\"C\"", StrSize) == 0)
|
|
|
|
|
Language = LinkageSpecDecl::lang_c;
|
|
|
|
|
else if (strncmp(Lang, "\"C++\"", StrSize) == 0)
|
|
|
|
|
Language = LinkageSpecDecl::lang_cxx;
|
|
|
|
|
else {
|
2009-01-06 03:45:36 +08:00
|
|
|
|
Diag(LangLoc, diag::err_bad_language);
|
2009-03-29 03:18:32 +08:00
|
|
|
|
return DeclPtrTy();
|
2008-12-17 15:13:27 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2008-12-17 15:13:27 +08:00
|
|
|
|
// FIXME: Add all the various semantics of linkage specifications
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-01-06 03:45:36 +08:00
|
|
|
|
LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext,
|
2009-09-09 23:08:12 +08:00
|
|
|
|
LangLoc, Language,
|
2009-01-06 03:45:36 +08:00
|
|
|
|
LBraceLoc.isValid());
|
2009-06-30 10:36:12 +08:00
|
|
|
|
CurContext->addDecl(D);
|
2009-01-06 03:45:36 +08:00
|
|
|
|
PushDeclContext(S, D);
|
2009-03-29 03:18:32 +08:00
|
|
|
|
return DeclPtrTy::make(D);
|
2008-12-17 15:13:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-01-06 03:45:36 +08:00
|
|
|
|
/// ActOnFinishLinkageSpecification - Completely the definition of
|
|
|
|
|
/// the C++ linkage specification LinkageSpec. If RBraceLoc is
|
|
|
|
|
/// valid, it's the position of the closing '}' brace in a linkage
|
|
|
|
|
/// specification that uses braces.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
Sema::DeclPtrTy Sema::ActOnFinishLinkageSpecification(Scope *S,
|
|
|
|
|
DeclPtrTy LinkageSpec,
|
|
|
|
|
SourceLocation RBraceLoc) {
|
2009-01-06 03:45:36 +08:00
|
|
|
|
if (LinkageSpec)
|
|
|
|
|
PopDeclContext();
|
|
|
|
|
return LinkageSpec;
|
2008-12-17 15:09:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-05-19 04:51:54 +08:00
|
|
|
|
/// \brief Perform semantic analysis for the variable declaration that
|
|
|
|
|
/// occurs within a C++ catch clause, returning the newly-created
|
|
|
|
|
/// variable.
|
|
|
|
|
VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType,
|
2009-08-19 09:27:57 +08:00
|
|
|
|
DeclaratorInfo *DInfo,
|
2009-05-19 04:51:54 +08:00
|
|
|
|
IdentifierInfo *Name,
|
|
|
|
|
SourceLocation Loc,
|
|
|
|
|
SourceRange Range) {
|
|
|
|
|
bool Invalid = false;
|
2008-12-23 03:15:10 +08:00
|
|
|
|
|
|
|
|
|
// Arrays and functions decay.
|
|
|
|
|
if (ExDeclType->isArrayType())
|
|
|
|
|
ExDeclType = Context.getArrayDecayedType(ExDeclType);
|
|
|
|
|
else if (ExDeclType->isFunctionType())
|
|
|
|
|
ExDeclType = Context.getPointerType(ExDeclType);
|
|
|
|
|
|
|
|
|
|
// C++ 15.3p1: The exception-declaration shall not denote an incomplete type.
|
|
|
|
|
// The exception-declaration shall not denote a pointer or reference to an
|
|
|
|
|
// incomplete type, other than [cv] void*.
|
2009-03-23 07:49:27 +08:00
|
|
|
|
// N2844 forbids rvalue references.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (!ExDeclType->isDependentType() && ExDeclType->isRValueReferenceType()) {
|
2009-05-19 04:51:54 +08:00
|
|
|
|
Diag(Loc, diag::err_catch_rvalue_ref) << Range;
|
2009-03-23 07:49:27 +08:00
|
|
|
|
Invalid = true;
|
|
|
|
|
}
|
2009-05-19 04:51:54 +08:00
|
|
|
|
|
2008-12-23 03:15:10 +08:00
|
|
|
|
QualType BaseType = ExDeclType;
|
|
|
|
|
int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference
|
2009-01-20 03:26:10 +08:00
|
|
|
|
unsigned DK = diag::err_catch_incomplete;
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
|
2008-12-23 03:15:10 +08:00
|
|
|
|
BaseType = Ptr->getPointeeType();
|
|
|
|
|
Mode = 1;
|
2009-01-20 03:26:10 +08:00
|
|
|
|
DK = diag::err_catch_incomplete_ptr;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
} else if (const ReferenceType *Ref = BaseType->getAs<ReferenceType>()) {
|
2009-03-23 07:49:27 +08:00
|
|
|
|
// For the purpose of error recovery, we treat rvalue refs like lvalue refs.
|
2008-12-23 03:15:10 +08:00
|
|
|
|
BaseType = Ref->getPointeeType();
|
|
|
|
|
Mode = 2;
|
2009-01-20 03:26:10 +08:00
|
|
|
|
DK = diag::err_catch_incomplete_ref;
|
2008-12-23 03:15:10 +08:00
|
|
|
|
}
|
2009-03-23 07:49:27 +08:00
|
|
|
|
if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) &&
|
2009-05-19 04:51:54 +08:00
|
|
|
|
!BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK))
|
2008-12-23 03:15:10 +08:00
|
|
|
|
Invalid = true;
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (!Invalid && !ExDeclType->isDependentType() &&
|
2009-05-19 04:51:54 +08:00
|
|
|
|
RequireNonAbstractType(Loc, ExDeclType,
|
|
|
|
|
diag::err_abstract_type_in_decl,
|
|
|
|
|
AbstractVariableType))
|
2009-04-28 05:03:30 +08:00
|
|
|
|
Invalid = true;
|
|
|
|
|
|
2009-05-19 04:51:54 +08:00
|
|
|
|
// FIXME: Need to test for ability to copy-construct and destroy the
|
|
|
|
|
// exception variable.
|
|
|
|
|
|
2008-12-23 05:35:02 +08:00
|
|
|
|
// FIXME: Need to check for abstract classes.
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc,
|
2009-08-21 08:31:54 +08:00
|
|
|
|
Name, ExDeclType, DInfo, VarDecl::None);
|
2009-05-19 04:51:54 +08:00
|
|
|
|
|
|
|
|
|
if (Invalid)
|
|
|
|
|
ExDecl->setInvalidDecl();
|
|
|
|
|
|
|
|
|
|
return ExDecl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch
|
|
|
|
|
/// handler.
|
|
|
|
|
Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
|
2009-08-19 09:27:57 +08:00
|
|
|
|
DeclaratorInfo *DInfo = 0;
|
|
|
|
|
QualType ExDeclType = GetTypeForDeclarator(D, S, &DInfo);
|
2009-05-19 04:51:54 +08:00
|
|
|
|
|
|
|
|
|
bool Invalid = D.isInvalidType();
|
2008-12-23 03:15:10 +08:00
|
|
|
|
IdentifierInfo *II = D.getIdentifier();
|
2009-02-05 01:27:36 +08:00
|
|
|
|
if (NamedDecl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) {
|
2008-12-23 03:15:10 +08:00
|
|
|
|
// The scope should be freshly made just for us. There is just no way
|
|
|
|
|
// it contains any previous declaration.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
assert(!S->isDeclScope(DeclPtrTy::make(PrevDecl)));
|
2008-12-23 03:15:10 +08:00
|
|
|
|
if (PrevDecl->isTemplateParameter()) {
|
|
|
|
|
// Maybe we will complain about the shadowed template parameter.
|
|
|
|
|
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 16:06:05 +08:00
|
|
|
|
if (D.getCXXScopeSpec().isSet() && !Invalid) {
|
2008-12-23 03:15:10 +08:00
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_qualified_catch_declarator)
|
|
|
|
|
<< D.getCXXScopeSpec().getRange();
|
2009-04-25 16:06:05 +08:00
|
|
|
|
Invalid = true;
|
2008-12-23 03:15:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-19 09:27:57 +08:00
|
|
|
|
VarDecl *ExDecl = BuildExceptionDeclaration(S, ExDeclType, DInfo,
|
2009-05-19 04:51:54 +08:00
|
|
|
|
D.getIdentifier(),
|
|
|
|
|
D.getIdentifierLoc(),
|
|
|
|
|
D.getDeclSpec().getSourceRange());
|
|
|
|
|
|
2009-04-25 16:06:05 +08:00
|
|
|
|
if (Invalid)
|
|
|
|
|
ExDecl->setInvalidDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2008-12-23 03:15:10 +08:00
|
|
|
|
// Add the exception declaration into this scope.
|
|
|
|
|
if (II)
|
2009-05-19 04:51:54 +08:00
|
|
|
|
PushOnScopeChains(ExDecl, S);
|
|
|
|
|
else
|
2009-06-30 10:36:12 +08:00
|
|
|
|
CurContext->addDecl(ExDecl);
|
2008-12-23 03:15:10 +08:00
|
|
|
|
|
2009-06-18 05:51:59 +08:00
|
|
|
|
ProcessDeclAttributes(S, ExDecl, D);
|
2009-03-29 03:18:32 +08:00
|
|
|
|
return DeclPtrTy::make(ExDecl);
|
2008-12-23 03:15:10 +08:00
|
|
|
|
}
|
2009-03-14 08:25:26 +08:00
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
|
2009-03-29 03:18:32 +08:00
|
|
|
|
ExprArg assertexpr,
|
|
|
|
|
ExprArg assertmessageexpr) {
|
2009-03-14 08:25:26 +08:00
|
|
|
|
Expr *AssertExpr = (Expr *)assertexpr.get();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
StringLiteral *AssertMessage =
|
2009-03-14 08:25:26 +08:00
|
|
|
|
cast<StringLiteral>((Expr *)assertmessageexpr.get());
|
|
|
|
|
|
2009-03-14 08:33:21 +08:00
|
|
|
|
if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) {
|
|
|
|
|
llvm::APSInt Value(32);
|
|
|
|
|
if (!AssertExpr->isIntegerConstantExpr(Value, Context)) {
|
|
|
|
|
Diag(AssertLoc, diag::err_static_assert_expression_is_not_constant) <<
|
|
|
|
|
AssertExpr->getSourceRange();
|
2009-03-29 03:18:32 +08:00
|
|
|
|
return DeclPtrTy();
|
2009-03-14 08:33:21 +08:00
|
|
|
|
}
|
2009-03-14 08:25:26 +08:00
|
|
|
|
|
2009-03-14 08:33:21 +08:00
|
|
|
|
if (Value == 0) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
std::string str(AssertMessage->getStrData(),
|
2009-03-14 08:33:21 +08:00
|
|
|
|
AssertMessage->getByteLength());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(AssertLoc, diag::err_static_assert_failed)
|
2009-03-16 02:44:04 +08:00
|
|
|
|
<< str << AssertExpr->getSourceRange();
|
2009-03-14 08:33:21 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-16 01:35:16 +08:00
|
|
|
|
assertexpr.release();
|
|
|
|
|
assertmessageexpr.release();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Decl *Decl = StaticAssertDecl::Create(Context, CurContext, AssertLoc,
|
2009-03-14 08:25:26 +08:00
|
|
|
|
AssertExpr, AssertMessage);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-30 10:36:12 +08:00
|
|
|
|
CurContext->addDecl(Decl);
|
2009-03-29 03:18:32 +08:00
|
|
|
|
return DeclPtrTy::make(Decl);
|
2009-03-14 08:25:26 +08:00
|
|
|
|
}
|
2009-03-25 06:27:57 +08:00
|
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
|
Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S,
|
2009-09-12 05:02:39 +08:00
|
|
|
|
const DeclSpec &DS) {
|
2009-08-28 15:59:38 +08:00
|
|
|
|
SourceLocation Loc = DS.getSourceRange().getBegin();
|
2009-08-06 10:15:43 +08:00
|
|
|
|
|
|
|
|
|
assert(DS.isFriendSpecified());
|
|
|
|
|
assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
|
|
|
|
|
|
2009-09-09 01:47:29 +08:00
|
|
|
|
// Try to convert the decl specifier to a type.
|
|
|
|
|
bool invalid = false;
|
|
|
|
|
QualType T = ConvertDeclSpecToType(DS, Loc, invalid);
|
|
|
|
|
if (invalid) return DeclPtrTy();
|
2009-08-28 15:59:38 +08:00
|
|
|
|
|
|
|
|
|
// C++ [class.friend]p2:
|
|
|
|
|
// An elaborated-type-specifier shall be used in a friend declaration
|
|
|
|
|
// for a class.*
|
|
|
|
|
// * The class-key of the elaborated-type-specifier is required.
|
2009-09-09 01:47:29 +08:00
|
|
|
|
// This is one of the rare places in Clang where it's legitimate to
|
|
|
|
|
// ask about the "spelling" of the type.
|
|
|
|
|
if (!getLangOptions().CPlusPlus0x && !isa<ElaboratedType>(T)) {
|
|
|
|
|
// If we evaluated the type to a record type, suggest putting
|
|
|
|
|
// a tag in front.
|
2009-08-28 15:59:38 +08:00
|
|
|
|
if (const RecordType *RT = T->getAs<RecordType>()) {
|
2009-09-09 01:47:29 +08:00
|
|
|
|
RecordDecl *RD = RT->getDecl();
|
|
|
|
|
|
|
|
|
|
std::string InsertionText = std::string(" ") + RD->getKindName();
|
|
|
|
|
|
|
|
|
|
Diag(DS.getFriendSpecLoc(), diag::err_unelaborated_friend_type)
|
|
|
|
|
<< (RD->isUnion())
|
|
|
|
|
<< CodeModificationHint::CreateInsertion(DS.getTypeSpecTypeLoc(),
|
|
|
|
|
InsertionText);
|
2009-08-28 15:59:38 +08:00
|
|
|
|
return DeclPtrTy();
|
|
|
|
|
}else {
|
2009-09-09 01:47:29 +08:00
|
|
|
|
Diag(DS.getFriendSpecLoc(), diag::err_unexpected_friend)
|
|
|
|
|
<< DS.getSourceRange();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
return DeclPtrTy();
|
2009-08-06 10:15:43 +08:00
|
|
|
|
}
|
2009-08-28 15:59:38 +08:00
|
|
|
|
}
|
2009-08-06 10:15:43 +08:00
|
|
|
|
|
2009-09-12 05:02:39 +08:00
|
|
|
|
bool IsDefinition = false;
|
2009-09-09 01:47:29 +08:00
|
|
|
|
FriendDecl::FriendUnion FU = T.getTypePtr();
|
|
|
|
|
|
2009-09-12 05:02:39 +08:00
|
|
|
|
// We want to do a few things differently if the type was declared with
|
|
|
|
|
// a tag: specifically, we want to use the associated RecordDecl as
|
|
|
|
|
// the object of our friend declaration, and we want to disallow
|
|
|
|
|
// class definitions.
|
2009-09-09 01:47:29 +08:00
|
|
|
|
switch (DS.getTypeSpecType()) {
|
|
|
|
|
default: break;
|
|
|
|
|
case DeclSpec::TST_class:
|
|
|
|
|
case DeclSpec::TST_struct:
|
|
|
|
|
case DeclSpec::TST_union:
|
|
|
|
|
CXXRecordDecl *RD = cast_or_null<CXXRecordDecl>((Decl*) DS.getTypeRep());
|
|
|
|
|
if (RD) {
|
|
|
|
|
IsDefinition |= RD->isDefinition();
|
|
|
|
|
FU = RD;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2009-08-12 05:13:21 +08:00
|
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
|
// C++ [class.friend]p2: A class shall not be defined inside
|
|
|
|
|
// a friend declaration.
|
|
|
|
|
if (IsDefinition) {
|
|
|
|
|
Diag(DS.getFriendSpecLoc(), diag::err_friend_decl_defines_class)
|
|
|
|
|
<< DS.getSourceRange();
|
|
|
|
|
return DeclPtrTy();
|
|
|
|
|
}
|
2009-08-06 10:15:43 +08:00
|
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
|
// C++98 [class.friend]p1: A friend of a class is a function
|
|
|
|
|
// or class that is not a member of the class . . .
|
|
|
|
|
// But that's a silly restriction which nobody implements for
|
|
|
|
|
// inner classes, and C++0x removes it anyway, so we only report
|
|
|
|
|
// this (as a warning) if we're being pedantic.
|
2009-09-09 01:47:29 +08:00
|
|
|
|
if (!getLangOptions().CPlusPlus0x)
|
|
|
|
|
if (const RecordType *RT = T->getAs<RecordType>())
|
|
|
|
|
if (RT->getDecl()->getDeclContext() == CurContext)
|
|
|
|
|
Diag(DS.getFriendSpecLoc(), diag::ext_friend_inner_class);
|
2009-08-06 10:15:43 +08:00
|
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
|
FriendDecl *FD = FriendDecl::Create(Context, CurContext, Loc, FU,
|
|
|
|
|
DS.getFriendSpecLoc());
|
2009-08-29 11:50:18 +08:00
|
|
|
|
FD->setAccess(AS_public);
|
2009-08-28 15:59:38 +08:00
|
|
|
|
CurContext->addDecl(FD);
|
2009-08-06 10:15:43 +08:00
|
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
|
return DeclPtrTy::make(FD);
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-12 05:02:39 +08:00
|
|
|
|
Sema::DeclPtrTy
|
|
|
|
|
Sema::ActOnFriendFunctionDecl(Scope *S,
|
|
|
|
|
Declarator &D,
|
|
|
|
|
bool IsDefinition,
|
|
|
|
|
MultiTemplateParamsArg TemplateParams) {
|
|
|
|
|
// FIXME: do something with template parameters
|
|
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
|
const DeclSpec &DS = D.getDeclSpec();
|
|
|
|
|
|
|
|
|
|
assert(DS.isFriendSpecified());
|
|
|
|
|
assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
|
|
|
|
|
|
|
|
|
|
SourceLocation Loc = D.getIdentifierLoc();
|
2009-08-19 09:27:57 +08:00
|
|
|
|
DeclaratorInfo *DInfo = 0;
|
2009-08-28 15:59:38 +08:00
|
|
|
|
QualType T = GetTypeForDeclarator(D, S, &DInfo);
|
2009-08-06 10:15:43 +08:00
|
|
|
|
|
|
|
|
|
// C++ [class.friend]p1
|
|
|
|
|
// A friend of a class is a function or class....
|
|
|
|
|
// Note that this sees through typedefs, which is intended.
|
2009-08-28 15:59:38 +08:00
|
|
|
|
// It *doesn't* see through dependent types, which is correct
|
|
|
|
|
// according to [temp.arg.type]p3:
|
|
|
|
|
// If a declaration acquires a function type through a
|
|
|
|
|
// type dependent on a template-parameter and this causes
|
|
|
|
|
// a declaration that does not use the syntactic form of a
|
|
|
|
|
// function declarator to have a function type, the program
|
|
|
|
|
// is ill-formed.
|
2009-08-06 10:15:43 +08:00
|
|
|
|
if (!T->isFunctionType()) {
|
|
|
|
|
Diag(Loc, diag::err_unexpected_friend);
|
|
|
|
|
|
|
|
|
|
// It might be worthwhile to try to recover by creating an
|
|
|
|
|
// appropriate declaration.
|
|
|
|
|
return DeclPtrTy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// C++ [namespace.memdef]p3
|
|
|
|
|
// - If a friend declaration in a non-local class first declares a
|
|
|
|
|
// class or function, the friend class or function is a member
|
|
|
|
|
// of the innermost enclosing namespace.
|
|
|
|
|
// - The name of the friend is not found by simple name lookup
|
|
|
|
|
// until a matching declaration is provided in that namespace
|
|
|
|
|
// scope (either before or after the class declaration granting
|
|
|
|
|
// friendship).
|
|
|
|
|
// - If a friend function is called, its name may be found by the
|
|
|
|
|
// name lookup that considers functions from namespaces and
|
|
|
|
|
// classes associated with the types of the function arguments.
|
|
|
|
|
// - When looking for a prior declaration of a class or a function
|
|
|
|
|
// declared as a friend, scopes outside the innermost enclosing
|
|
|
|
|
// namespace scope are not considered.
|
|
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
|
CXXScopeSpec &ScopeQual = D.getCXXScopeSpec();
|
|
|
|
|
DeclarationName Name = GetNameForDeclarator(D);
|
2009-08-06 10:15:43 +08:00
|
|
|
|
assert(Name);
|
|
|
|
|
|
|
|
|
|
// The existing declaration we found.
|
|
|
|
|
FunctionDecl *FD = NULL;
|
|
|
|
|
|
|
|
|
|
// The context we found the declaration in, or in which we should
|
|
|
|
|
// create the declaration.
|
|
|
|
|
DeclContext *DC;
|
|
|
|
|
|
|
|
|
|
// FIXME: handle local classes
|
|
|
|
|
|
|
|
|
|
// Recover from invalid scope qualifiers as if they just weren't there.
|
|
|
|
|
if (!ScopeQual.isInvalid() && ScopeQual.isSet()) {
|
|
|
|
|
DC = computeDeclContext(ScopeQual);
|
|
|
|
|
|
|
|
|
|
// FIXME: handle dependent contexts
|
|
|
|
|
if (!DC) return DeclPtrTy();
|
|
|
|
|
|
|
|
|
|
Decl *Dec = LookupQualifiedNameWithType(DC, Name, T);
|
|
|
|
|
|
|
|
|
|
// If searching in that context implicitly found a declaration in
|
|
|
|
|
// a different context, treat it like it wasn't found at all.
|
|
|
|
|
// TODO: better diagnostics for this case. Suggesting the right
|
|
|
|
|
// qualified scope would be nice...
|
|
|
|
|
if (!Dec || Dec->getDeclContext() != DC) {
|
2009-08-28 15:59:38 +08:00
|
|
|
|
D.setInvalidType();
|
2009-08-06 10:15:43 +08:00
|
|
|
|
Diag(Loc, diag::err_qualified_friend_not_found) << Name << T;
|
|
|
|
|
return DeclPtrTy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// C++ [class.friend]p1: A friend of a class is a function or
|
|
|
|
|
// class that is not a member of the class . . .
|
|
|
|
|
if (DC == CurContext)
|
|
|
|
|
Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
|
|
|
|
|
|
|
|
|
|
FD = cast<FunctionDecl>(Dec);
|
|
|
|
|
|
|
|
|
|
// Otherwise walk out to the nearest namespace scope looking for matches.
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: handle local class contexts.
|
|
|
|
|
|
|
|
|
|
DC = CurContext;
|
|
|
|
|
while (true) {
|
|
|
|
|
// Skip class contexts. If someone can cite chapter and verse
|
|
|
|
|
// for this behavior, that would be nice --- it's what GCC and
|
|
|
|
|
// EDG do, and it seems like a reasonable intent, but the spec
|
|
|
|
|
// really only says that checks for unqualified existing
|
|
|
|
|
// declarations should stop at the nearest enclosing namespace,
|
|
|
|
|
// not that they should only consider the nearest enclosing
|
|
|
|
|
// namespace.
|
|
|
|
|
while (DC->isRecord()) DC = DC->getParent();
|
|
|
|
|
|
|
|
|
|
Decl *Dec = LookupQualifiedNameWithType(DC, Name, T);
|
|
|
|
|
|
|
|
|
|
// TODO: decide what we think about using declarations.
|
|
|
|
|
if (Dec) {
|
|
|
|
|
FD = cast<FunctionDecl>(Dec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (DC->isFileContext()) break;
|
|
|
|
|
DC = DC->getParent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// C++ [class.friend]p1: A friend of a class is a function or
|
|
|
|
|
// class that is not a member of the class . . .
|
2009-08-07 04:49:32 +08:00
|
|
|
|
// C++0x changes this for both friend types and functions.
|
|
|
|
|
// Most C++ 98 compilers do seem to give an error here, so
|
|
|
|
|
// we do, too.
|
|
|
|
|
if (FD && DC == CurContext && !getLangOptions().CPlusPlus0x)
|
2009-08-06 10:15:43 +08:00
|
|
|
|
Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-11 14:59:38 +08:00
|
|
|
|
bool Redeclaration = (FD != 0);
|
|
|
|
|
|
|
|
|
|
// If we found a match, create a friend function declaration with
|
|
|
|
|
// that function as the previous declaration.
|
|
|
|
|
if (Redeclaration) {
|
|
|
|
|
// Create it in the semantic context of the original declaration.
|
|
|
|
|
DC = FD->getDeclContext();
|
|
|
|
|
|
2009-08-06 10:15:43 +08:00
|
|
|
|
// If we didn't find something matching the type exactly, create
|
|
|
|
|
// a declaration. This declaration should only be findable via
|
|
|
|
|
// argument-dependent lookup.
|
2009-08-11 14:59:38 +08:00
|
|
|
|
} else {
|
2009-08-06 10:15:43 +08:00
|
|
|
|
assert(DC->isFileContext());
|
|
|
|
|
|
|
|
|
|
// This implies that it has to be an operator or function.
|
2009-08-28 15:59:38 +08:00
|
|
|
|
if (D.getKind() == Declarator::DK_Constructor ||
|
|
|
|
|
D.getKind() == Declarator::DK_Destructor ||
|
|
|
|
|
D.getKind() == Declarator::DK_Conversion) {
|
2009-08-06 10:15:43 +08:00
|
|
|
|
Diag(Loc, diag::err_introducing_special_friend) <<
|
2009-08-28 15:59:38 +08:00
|
|
|
|
(D.getKind() == Declarator::DK_Constructor ? 0 :
|
|
|
|
|
D.getKind() == Declarator::DK_Destructor ? 1 : 2);
|
2009-08-06 10:15:43 +08:00
|
|
|
|
return DeclPtrTy();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
|
NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo,
|
2009-08-11 14:59:38 +08:00
|
|
|
|
/* PrevDecl = */ FD,
|
|
|
|
|
MultiTemplateParamsArg(*this),
|
|
|
|
|
IsDefinition,
|
|
|
|
|
Redeclaration);
|
2009-08-28 15:59:38 +08:00
|
|
|
|
if (!ND) return DeclPtrTy();
|
2009-09-01 06:39:49 +08:00
|
|
|
|
|
|
|
|
|
assert(cast<FunctionDecl>(ND)->getPreviousDeclaration() == FD &&
|
|
|
|
|
"lost reference to previous declaration");
|
|
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
|
FD = cast<FunctionDecl>(ND);
|
2009-08-11 14:59:38 +08:00
|
|
|
|
|
2009-08-18 08:00:49 +08:00
|
|
|
|
assert(FD->getDeclContext() == DC);
|
|
|
|
|
assert(FD->getLexicalDeclContext() == CurContext);
|
|
|
|
|
|
2009-09-01 06:39:49 +08:00
|
|
|
|
// Add the function declaration to the appropriate lookup tables,
|
|
|
|
|
// adjusting the redeclarations list as necessary. We don't
|
|
|
|
|
// want to do this yet if the friending class is dependent.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
//
|
2009-09-01 06:39:49 +08:00
|
|
|
|
// Also update the scope-based lookup if the target context's
|
|
|
|
|
// lookup context is in lexical scope.
|
|
|
|
|
if (!CurContext->isDependentContext()) {
|
|
|
|
|
DC = DC->getLookupContext();
|
|
|
|
|
DC->makeDeclVisibleInContext(FD, /* Recoverable=*/ false);
|
|
|
|
|
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
|
|
|
|
|
PushOnScopeChains(FD, EnclosingScope, /*AddToContext=*/ false);
|
|
|
|
|
}
|
2009-08-28 15:59:38 +08:00
|
|
|
|
|
|
|
|
|
FriendDecl *FrD = FriendDecl::Create(Context, CurContext,
|
|
|
|
|
D.getIdentifierLoc(), FD,
|
|
|
|
|
DS.getFriendSpecLoc());
|
2009-08-29 11:50:18 +08:00
|
|
|
|
FrD->setAccess(AS_public);
|
2009-08-28 15:59:38 +08:00
|
|
|
|
CurContext->addDecl(FrD);
|
2009-08-06 10:15:43 +08:00
|
|
|
|
|
|
|
|
|
return DeclPtrTy::make(FD);
|
2009-05-12 06:55:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-03-29 03:18:32 +08:00
|
|
|
|
void Sema::SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc) {
|
2009-08-24 19:57:43 +08:00
|
|
|
|
AdjustDeclIfTemplate(dcl);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-29 03:18:32 +08:00
|
|
|
|
Decl *Dcl = dcl.getAs<Decl>();
|
2009-03-25 06:27:57 +08:00
|
|
|
|
FunctionDecl *Fn = dyn_cast<FunctionDecl>(Dcl);
|
|
|
|
|
if (!Fn) {
|
|
|
|
|
Diag(DelLoc, diag::err_deleted_non_function);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (const FunctionDecl *Prev = Fn->getPreviousDeclaration()) {
|
|
|
|
|
Diag(DelLoc, diag::err_deleted_decl_not_first);
|
|
|
|
|
Diag(Prev->getLocation(), diag::note_previous_declaration);
|
|
|
|
|
// If the declaration wasn't the first, we delete the function anyway for
|
|
|
|
|
// recovery.
|
|
|
|
|
}
|
|
|
|
|
Fn->setDeleted();
|
|
|
|
|
}
|
2009-04-28 05:33:24 +08:00
|
|
|
|
|
|
|
|
|
static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
|
|
|
|
|
for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E;
|
|
|
|
|
++CI) {
|
|
|
|
|
Stmt *SubStmt = *CI;
|
|
|
|
|
if (!SubStmt)
|
|
|
|
|
continue;
|
|
|
|
|
if (isa<ReturnStmt>(SubStmt))
|
|
|
|
|
Self.Diag(SubStmt->getSourceRange().getBegin(),
|
|
|
|
|
diag::err_return_in_constructor_handler);
|
|
|
|
|
if (!isa<Expr>(SubStmt))
|
|
|
|
|
SearchForReturnInStmt(Self, SubStmt);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) {
|
|
|
|
|
for (unsigned I = 0, E = TryBlock->getNumHandlers(); I != E; ++I) {
|
|
|
|
|
CXXCatchStmt *Handler = TryBlock->getHandler(I);
|
|
|
|
|
SearchForReturnInStmt(*this, Handler);
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-05-14 09:09:04 +08:00
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
|
2009-05-14 09:09:04 +08:00
|
|
|
|
const CXXMethodDecl *Old) {
|
|
|
|
|
QualType NewTy = New->getType()->getAsFunctionType()->getResultType();
|
|
|
|
|
QualType OldTy = Old->getType()->getAsFunctionType()->getResultType();
|
|
|
|
|
|
|
|
|
|
QualType CNewTy = Context.getCanonicalType(NewTy);
|
|
|
|
|
QualType COldTy = Context.getCanonicalType(OldTy);
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CNewTy == COldTy &&
|
2009-05-14 09:09:04 +08:00
|
|
|
|
CNewTy.getCVRQualifiers() == COldTy.getCVRQualifiers())
|
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-05-15 03:52:19 +08:00
|
|
|
|
// Check if the return types are covariant
|
|
|
|
|
QualType NewClassTy, OldClassTy;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-05-15 03:52:19 +08:00
|
|
|
|
/// Both types must be pointers or references to classes.
|
|
|
|
|
if (PointerType *NewPT = dyn_cast<PointerType>(NewTy)) {
|
|
|
|
|
if (PointerType *OldPT = dyn_cast<PointerType>(OldTy)) {
|
|
|
|
|
NewClassTy = NewPT->getPointeeType();
|
|
|
|
|
OldClassTy = OldPT->getPointeeType();
|
|
|
|
|
}
|
|
|
|
|
} else if (ReferenceType *NewRT = dyn_cast<ReferenceType>(NewTy)) {
|
|
|
|
|
if (ReferenceType *OldRT = dyn_cast<ReferenceType>(OldTy)) {
|
|
|
|
|
NewClassTy = NewRT->getPointeeType();
|
|
|
|
|
OldClassTy = OldRT->getPointeeType();
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-05-15 03:52:19 +08:00
|
|
|
|
// The return types aren't either both pointers or references to a class type.
|
|
|
|
|
if (NewClassTy.isNull()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Diag(New->getLocation(),
|
2009-05-15 03:52:19 +08:00
|
|
|
|
diag::err_different_return_type_for_overriding_virtual_function)
|
|
|
|
|
<< New->getDeclName() << NewTy << OldTy;
|
|
|
|
|
Diag(Old->getLocation(), diag::note_overridden_virtual_function);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-05-15 03:52:19 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2009-05-14 09:09:04 +08:00
|
|
|
|
|
2009-05-15 03:52:19 +08:00
|
|
|
|
if (NewClassTy.getUnqualifiedType() != OldClassTy.getUnqualifiedType()) {
|
|
|
|
|
// Check if the new class derives from the old class.
|
|
|
|
|
if (!IsDerivedFrom(NewClassTy, OldClassTy)) {
|
|
|
|
|
Diag(New->getLocation(),
|
|
|
|
|
diag::err_covariant_return_not_derived)
|
|
|
|
|
<< New->getDeclName() << NewTy << OldTy;
|
|
|
|
|
Diag(Old->getLocation(), diag::note_overridden_virtual_function);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-05-15 03:52:19 +08:00
|
|
|
|
// Check if we the conversion from derived to base is valid.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy,
|
2009-05-15 03:52:19 +08:00
|
|
|
|
diag::err_covariant_return_inaccessible_base,
|
|
|
|
|
diag::err_covariant_return_ambiguous_derived_to_base_conv,
|
|
|
|
|
// FIXME: Should this point to the return type?
|
|
|
|
|
New->getLocation(), SourceRange(), New->getDeclName())) {
|
|
|
|
|
Diag(Old->getLocation(), diag::note_overridden_virtual_function);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-05-15 03:52:19 +08:00
|
|
|
|
// The qualifiers of the return types must be the same.
|
|
|
|
|
if (CNewTy.getCVRQualifiers() != COldTy.getCVRQualifiers()) {
|
|
|
|
|
Diag(New->getLocation(),
|
|
|
|
|
diag::err_covariant_return_type_different_qualifications)
|
2009-05-14 09:09:04 +08:00
|
|
|
|
<< New->getDeclName() << NewTy << OldTy;
|
2009-05-15 03:52:19 +08:00
|
|
|
|
Diag(Old->getLocation(), diag::note_overridden_virtual_function);
|
|
|
|
|
return true;
|
|
|
|
|
};
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-05-15 03:52:19 +08:00
|
|
|
|
|
|
|
|
|
// The new class type must have the same or less qualifiers as the old type.
|
|
|
|
|
if (NewClassTy.isMoreQualifiedThan(OldClassTy)) {
|
|
|
|
|
Diag(New->getLocation(),
|
|
|
|
|
diag::err_covariant_return_type_class_type_more_qualified)
|
|
|
|
|
<< New->getDeclName() << NewTy << OldTy;
|
|
|
|
|
Diag(Old->getLocation(), diag::note_overridden_virtual_function);
|
|
|
|
|
return true;
|
|
|
|
|
};
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-05-15 03:52:19 +08:00
|
|
|
|
return false;
|
2009-05-14 09:09:04 +08:00
|
|
|
|
}
|
2009-06-18 06:50:06 +08:00
|
|
|
|
|
2009-07-08 04:29:57 +08:00
|
|
|
|
bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
|
2009-09-09 23:08:12 +08:00
|
|
|
|
const CXXMethodDecl *Old) {
|
2009-07-08 04:29:57 +08:00
|
|
|
|
return CheckExceptionSpecSubset(diag::err_override_exception_spec,
|
|
|
|
|
diag::note_overridden_virtual_function,
|
|
|
|
|
Old->getType()->getAsFunctionProtoType(),
|
|
|
|
|
Old->getLocation(),
|
|
|
|
|
New->getType()->getAsFunctionProtoType(),
|
|
|
|
|
New->getLocation());
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-18 06:50:06 +08:00
|
|
|
|
/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
|
|
|
|
|
/// initializer for the declaration 'Dcl'.
|
|
|
|
|
/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
|
|
|
|
|
/// static data member of class X, names should be looked up in the scope of
|
|
|
|
|
/// class X.
|
|
|
|
|
void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) {
|
2009-08-24 19:57:43 +08:00
|
|
|
|
AdjustDeclIfTemplate(Dcl);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-18 06:50:06 +08:00
|
|
|
|
Decl *D = Dcl.getAs<Decl>();
|
|
|
|
|
// If there is no declaration, there was an error parsing it.
|
|
|
|
|
if (D == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Check whether it is a declaration with a nested name specifier like
|
|
|
|
|
// int foo::bar;
|
|
|
|
|
if (!D->isOutOfLine())
|
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-18 06:50:06 +08:00
|
|
|
|
// C++ [basic.lookup.unqual]p13
|
|
|
|
|
//
|
|
|
|
|
// A name used in the definition of a static data member of class X
|
|
|
|
|
// (after the qualified-id of the static member) is looked up as if the name
|
|
|
|
|
// was used in a member function of X.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-18 06:50:06 +08:00
|
|
|
|
// Change current context into the context of the initializing declaration.
|
2009-06-18 07:15:40 +08:00
|
|
|
|
EnterDeclaratorContext(S, D->getDeclContext());
|
2009-06-18 06:50:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
|
|
|
|
|
/// initializer for the declaration 'Dcl'.
|
|
|
|
|
void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) {
|
2009-08-24 19:57:43 +08:00
|
|
|
|
AdjustDeclIfTemplate(Dcl);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-06-18 06:50:06 +08:00
|
|
|
|
Decl *D = Dcl.getAs<Decl>();
|
|
|
|
|
// If there is no declaration, there was an error parsing it.
|
|
|
|
|
if (D == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Check whether it is a declaration with a nested name specifier like
|
|
|
|
|
// int foo::bar;
|
|
|
|
|
if (!D->isOutOfLine())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
assert(S->getEntity() == D->getDeclContext() && "Context imbalance!");
|
2009-06-18 07:15:40 +08:00
|
|
|
|
ExitDeclaratorContext(S);
|
2009-06-18 06:50:06 +08:00
|
|
|
|
}
|