Newer
Older
//===------ SemaDeclCXX.cpp - Semantic Analysis for C++ Declarations ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements semantic analysis for C++ declarations.
//
//===----------------------------------------------------------------------===//
#include "Sema.h"
#include "SemaInherit.h"
Argyrios Kyrtzidis
committed
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/AST/StmtVisitor.h"
Argyrios Kyrtzidis
committed
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
#include <algorithm> // for std::equal
#include <map>
using namespace clang;
//===----------------------------------------------------------------------===//
// CheckDefaultArgumentVisitor
//===----------------------------------------------------------------------===//
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.
class VISIBILITY_HIDDEN CheckDefaultArgumentVisitor
: public StmtVisitor<CheckDefaultArgumentVisitor, bool> {
Expr *DefaultArg;
Sema *S;
public:
CheckDefaultArgumentVisitor(Expr *defarg, Sema *s)
: DefaultArg(defarg), S(s) {}
bool VisitExpr(Expr *Node);
bool VisitDeclRefExpr(DeclRefExpr *DRE);
Douglas Gregor
committed
bool VisitCXXThisExpr(CXXThisExpr *ThisE);
};
/// VisitExpr - Visit all of the children of this expression.
bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) {
bool IsInvalid = false;
for (Stmt::child_iterator I = Node->child_begin(),
E = Node->child_end(); I != E; ++I)
IsInvalid |= Visit(*I);
return IsInvalid;
/// 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) {
NamedDecl *Decl = DRE->getDecl();
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.
return S->Diag(DRE->getSourceRange().getBegin(),
diag::err_param_default_argument_references_param)
<< Param->getDeclName() << DefaultArg->getSourceRange();
} else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) {
// C++ [dcl.fct.default]p7
// Local variables shall not be used in default argument
// expressions.
if (VDecl->isBlockVarDecl())
return S->Diag(DRE->getSourceRange().getBegin(),
diag::err_param_default_argument_references_local)
<< VDecl->getDeclName() << DefaultArg->getSourceRange();
Douglas Gregor
committed
return false;
}
Douglas Gregor
committed
/// 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(),
diag::err_param_default_argument_references_this)
<< ThisE->getSourceRange();
}
/// ActOnParamDefaultArgument - Check whether the default argument
/// provided for a function parameter is well-formed. If so, attach it
/// to the parameter declaration.
Chris Lattner
committed
Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
ExprArg defarg) {
Chris Lattner
committed
ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
ExprOwningPtr<Expr> DefaultArg(this, (Expr *)defarg.release());
QualType ParamType = Param->getType();
// Default arguments are only permitted in C++
if (!getLangOptions().CPlusPlus) {
Diag(EqualLoc, diag::err_param_default_argument)
<< DefaultArg->getSourceRange();
Param->setInvalidDecl();
return;
}
// C++ [dcl.fct.default]p5
// A default argument expression is implicitly converted (clause
// 4) to the parameter type. The default argument expression has
// the same semantic constraints as the initializer expression in
// a declaration of a variable of the parameter type, using the
// copy-initialization semantics (8.5).
Expr *DefaultArgPtr = DefaultArg.get();
bool DefaultInitFailed = CheckInitializerTypes(DefaultArgPtr, ParamType,
EqualLoc,
Param->getDeclName(),
/*DirectInit=*/false);
if (DefaultArgPtr != DefaultArg.get()) {
DefaultArg.take();
DefaultArg.reset(DefaultArgPtr);
}
Douglas Gregor
committed
if (DefaultInitFailed) {
return;
}
// Check that the default argument is well-formed
CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg.get(), this);
if (DefaultArgChecker.Visit(DefaultArg.get())) {
Param->setInvalidDecl();
}
// Okay: add the default argument to the parameter
Param->setDefaultArg(DefaultArg.take());
}
/// ActOnParamUnparsedDefaultArgument - We've seen a default
/// argument for a function parameter, but we can't parse it yet
/// because we're inside a class definition. Note that this default
/// argument will be parsed later.
Chris Lattner
committed
void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
SourceLocation EqualLoc) {
Chris Lattner
committed
ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
if (Param)
Param->setUnparsedDefaultArg();
}
/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
/// the default argument for the parameter param failed.
Chris Lattner
committed
void Sema::ActOnParamDefaultArgumentError(DeclPtrTy param) {
cast<ParmVarDecl>(param.getAs<Decl>())->setInvalidDecl();
}
Douglas Gregor
committed
/// 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.
Chris Lattner
committed
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
Douglas Gregor
committed
DeclaratorChunk &chunk = D.getTypeObject(i);
if (chunk.Kind == DeclaratorChunk::Function) {
Chris Lattner
committed
for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) {
ParmVarDecl *Param =
cast<ParmVarDecl>(chunk.Fun.ArgInfo[argIdx].Param.getAs<Decl>());
if (Param->hasUnparsedDefaultArg()) {
CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens;
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
<< SourceRange((*Toks)[1].getLocation(), Toks->back().getLocation());
delete Toks;
chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0;
} else if (Param->getDefaultArg()) {
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
<< Param->getDefaultArg()->getSourceRange();
Param->setDefaultArg(0);
Douglas Gregor
committed
}
}
}
}
}
// MergeCXXFunctionDecl - Merge two declarations of the same C++
// function, once we already know that they have the same
// type. Subroutine of MergeFunctionDecl. Returns true if there was an
// error, false otherwise.
bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
bool Invalid = false;
// C++ [dcl.fct.default]p4:
//
// For non-template functions, default arguments can be added in
// later declarations of a function in the same
// scope. Declarations in different scopes have completely
// distinct sets of default arguments. That is, declarations in
// inner scopes do not acquire default arguments from
// declarations in outer scopes, and vice versa. In a given
// function declaration, all parameters subsequent to a
// parameter with a default argument shall have default
// arguments supplied in this or previous declarations. A
// default argument shall not be redefined by a later
// declaration (not even to the same value).
for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) {
ParmVarDecl *OldParam = Old->getParamDecl(p);
ParmVarDecl *NewParam = New->getParamDecl(p);
if(OldParam->getDefaultArg() && NewParam->getDefaultArg()) {
Diag(NewParam->getLocation(),
diag::err_param_default_argument_redefinition)
<< NewParam->getDefaultArg()->getSourceRange();
Diag(OldParam->getLocation(), diag::note_previous_definition);
Invalid = true;
} else if (OldParam->getDefaultArg()) {
// Merge the old default argument into the new parameter
NewParam->setDefaultArg(OldParam->getDefaultArg());
}
}
return Invalid;
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
}
/// CheckCXXDefaultArguments - Verify that the default arguments for a
/// function declaration are well-formed according to C++
/// [dcl.fct.default].
void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) {
unsigned NumParams = FD->getNumParams();
unsigned p;
// Find first parameter with a default argument
for (p = 0; p < NumParams; ++p) {
ParmVarDecl *Param = FD->getParamDecl(p);
if (Param->getDefaultArg())
break;
}
// C++ [dcl.fct.default]p4:
// In a given function declaration, all parameters
// subsequent to a parameter with a default argument shall
// have default arguments supplied in this or previous
// declarations. A default argument shall not be redefined
// by a later declaration (not even to the same value).
unsigned LastMissingDefaultArg = 0;
for(; p < NumParams; ++p) {
ParmVarDecl *Param = FD->getParamDecl(p);
if (!Param->getDefaultArg()) {
if (Param->isInvalidDecl())
/* We already complained about this parameter. */;
else if (Param->getIdentifier())
Diag(Param->getLocation(),
diag::err_param_default_argument_missing_name)
Chris Lattner
committed
<< Param->getIdentifier();
else
Diag(Param->getLocation(),
diag::err_param_default_argument_missing);
LastMissingDefaultArg = p;
}
}
if (LastMissingDefaultArg > 0) {
// Some default arguments were missing. Clear out all of the
// default arguments up to (and including) the last missing
// default argument, so that we leave the function parameters
// in a semantically valid state.
for (p = 0; p <= LastMissingDefaultArg; ++p) {
ParmVarDecl *Param = FD->getParamDecl(p);
if (Param->getDefaultArg()) {
if (!Param->hasUnparsedDefaultArg())
Param->getDefaultArg()->Destroy(Context);
Param->setDefaultArg(0);
}
}
}
}
/// 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.
Argyrios Kyrtzidis
committed
bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *,
const CXXScopeSpec *SS) {
CXXRecordDecl *CurDecl;
if (SS && SS->isSet() && !SS->isInvalid()) {
DeclContext *DC = computeDeclContext(*SS);
CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC);
} else
CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
if (CurDecl)
return &II == CurDecl->getIdentifier();
else
return false;
}
/// \brief Check the validity of a C++ base class specifier.
///
/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics
/// and returns NULL otherwise.
CXXBaseSpecifier *
Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
QualType BaseType,
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())
return new CXXBaseSpecifier(SpecifierRange, Virtual,
Class->getTagKind() == RecordDecl::TK_class,
Access, BaseType);
// Base specifiers must be record types.
if (!BaseType->isRecordType()) {
Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange;
return 0;
}
// C++ [class.union]p1:
// A union shall not be used as a base class.
if (BaseType->isUnionType()) {
Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange;
return 0;
}
// C++ [class.derived]p2:
// The class-name in a base-specifier shall not be an incompletely
// defined class.
if (RequireCompleteType(BaseLoc, BaseType, diag::err_incomplete_base_class,
SpecifierRange))
return 0;
// If the base class is polymorphic, the new one is, too.
RecordDecl *BaseDecl = BaseType->getAsRecordType()->getDecl();
assert(BaseDecl && "Record type has no declaration");
BaseDecl = BaseDecl->getDefinition(Context);
assert(BaseDecl && "Base type is not incomplete, but has no definition");
if (cast<CXXRecordDecl>(BaseDecl)->isPolymorphic())
Class->setPolymorphic(true);
// C++ [dcl.init.aggr]p1:
// An aggregate is [...] a class with [...] no base classes [...].
Class->setAggregate(false);
Class->setPOD(false);
// Create the base specifier.
// FIXME: Allocate via ASTContext?
return new CXXBaseSpecifier(SpecifierRange, Virtual,
Class->getTagKind() == RecordDecl::TK_class,
Access, BaseType);
}
/// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is
/// one entry in the base class list of a class specifier, for
/// example:
/// class foo : public bar, virtual private baz {
/// 'public bar' and 'virtual private baz' are each base-specifiers.
Sema::BaseResult
Chris Lattner
committed
Sema::ActOnBaseSpecifier(DeclPtrTy classdecl, SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
TypeTy *basetype, SourceLocation BaseLoc) {
AdjustDeclIfTemplate(classdecl);
Chris Lattner
committed
CXXRecordDecl *Class = cast<CXXRecordDecl>(classdecl.getAs<Decl>());
QualType BaseType = QualType::getFromOpaquePtr(basetype);
if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange,
Virtual, Access,
BaseType, BaseLoc))
return BaseSpec;
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;
// Used to keep track of which base types we have already seen, so
// that we can properly diagnose redundant direct base types. Note
// that the key is always the unqualified canonical type of the base
// class.
std::map<QualType, CXXBaseSpecifier*, QualTypeOrdering> KnownBaseTypes;
// Copy non-redundant base specifiers into permanent storage.
unsigned NumGoodBases = 0;
bool Invalid = false;
for (unsigned idx = 0; idx < NumBases; ++idx) {
QualType NewBaseType
= Context.getCanonicalType(Bases[idx]->getType());
NewBaseType = NewBaseType.getUnqualifiedType();
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.
Diag(Bases[idx]->getSourceRange().getBegin(),
diag::err_duplicate_base_class)
<< KnownBaseTypes[NewBaseType]->getType()
<< Bases[idx]->getSourceRange();
// Delete the duplicate base class specifier; we're going to
// overwrite its pointer later.
delete Bases[idx];
Invalid = true;
} else {
// Okay, add this new base class.
KnownBaseTypes[NewBaseType] = Bases[idx];
Bases[NumGoodBases++] = Bases[idx];
}
}
// Attach the remaining base class specifiers to the derived class.
Class->setBases(Bases, NumGoodBases);
// Delete the remaining (good) base class specifiers, since their
// data has been copied into the CXXRecordDecl.
for (unsigned idx = 0; idx < NumGoodBases; ++idx)
delete Bases[idx];
return Invalid;
}
/// ActOnBaseSpecifiers - Attach the given base specifiers to the
/// class, after checking whether there are any duplicate base
/// classes.
Chris Lattner
committed
void Sema::ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases,
unsigned NumBases) {
if (!ClassDecl || !Bases || !NumBases)
return;
AdjustDeclIfTemplate(ClassDecl);
Chris Lattner
committed
AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl.getAs<Decl>()),
(CXXBaseSpecifier**)(Bases), NumBases);
}
//===----------------------------------------------------------------------===//
// 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
Chris Lattner
committed
Sema::DeclPtrTy
Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Sebastian Redl
committed
ExprTy *BW, ExprTy *InitExpr, bool Deleted) {
const DeclSpec &DS = D.getDeclSpec();
DeclarationName Name = GetNameForDeclarator(D);
Expr *BitWidth = static_cast<Expr*>(BW);
Expr *Init = static_cast<Expr*>(InitExpr);
SourceLocation Loc = D.getIdentifierLoc();
bool isFunc = D.isFunctionDeclarator();
// C++ 9.2p6: A member shall not be declared to have automatic storage
// duration (auto, register) or with the extern storage-class-specifier.
// 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.
switch (DS.getStorageClassSpec()) {
case DeclSpec::SCS_unspecified:
case DeclSpec::SCS_typedef:
case DeclSpec::SCS_static:
// FALL THROUGH.
break;
case DeclSpec::SCS_mutable:
if (isFunc) {
if (DS.getStorageClassSpecLoc().isValid())
Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_function);
Diag(DS.getThreadSpecLoc(), diag::err_mutable_function);
Sebastian Redl
committed
// FIXME: It would be nicer if the keyword was ignored only for this
// declarator. Otherwise we could get follow-up errors.
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);
Sebastian Redl
committed
// FIXME: It would be nicer if the keyword was ignored only for this
// declarator. Otherwise we could get follow-up errors.
D.getMutableDeclSpec().ClearStorageClassSpecs();
}
}
break;
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();
}
D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_typename &&
// Check also for this case:
//
// typedef int f();
// f a;
//
QualType TDType = QualType::getFromOpaquePtr(DS.getTypeRep());
isFunc = TDType->isFunctionType();
bool isInstField = ((DS.getStorageClassSpec() == DeclSpec::SCS_unspecified ||
DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
if (isInstField) {
Douglas Gregor
committed
Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
AS);
assert(Member && "HandleField never returns null");
Member = ActOnDeclarator(S, D).getAs<Decl>();
if (!Member) {
if (BitWidth) DeleteExpr(BitWidth);
return DeclPtrTy();
// Non-instance-fields can't have a bitfield.
if (BitWidth) {
if (Member->isInvalidDecl()) {
// don't emit another diagnostic.
} else if (isa<VarDecl>(Member)) {
// 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)
<< Name << cast<ValueDecl>(Member)->getType()
<< BitWidth->getSourceRange();
}
DeleteExpr(BitWidth);
BitWidth = 0;
Member->setInvalidDecl();
}
Douglas Gregor
committed
Member->setAccess(AS);
assert((Name || isInstField) && "No identifier for non-field ?");
Douglas Gregor
committed
if (Init)
Chris Lattner
committed
AddInitializerToDecl(DeclPtrTy::make(Member), ExprArg(*this, Init), false);
Sebastian Redl
committed
if (Deleted) // FIXME: Source location is not very good.
SetDeclDeleted(DeclPtrTy::make(Member), D.getSourceRange().getBegin());
FieldCollector->Add(cast<FieldDecl>(Member));
return DeclPtrTy();
Chris Lattner
committed
return DeclPtrTy::make(Member);
/// ActOnMemInitializer - Handle a C++ member initializer.
Sema::MemInitResult
Chris Lattner
committed
Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
Scope *S,
IdentifierInfo *MemberOrBase,
SourceLocation IdLoc,
SourceLocation LParenLoc,
ExprTy **Args, unsigned NumArgs,
SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
CXXConstructorDecl *Constructor
Chris Lattner
committed
= dyn_cast<CXXConstructorDecl>(ConstructorD.getAs<Decl>());
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. ]
// Look for a member, first.
FieldDecl *Member = 0;
DeclContext::lookup_result Result
= ClassDecl->lookup(Context, MemberOrBase);
if (Result.first != Result.second)
Member = dyn_cast<FieldDecl>(*Result.first);
// FIXME: Handle members of an anonymous union.
if (Member) {
// FIXME: Perform direct initialization of the member.
return new CXXBaseOrMemberInitializer(Member, (Expr **)Args, NumArgs);
}
// It didn't name a member, so see if it names a class.
Douglas Gregor
committed
TypeTy *BaseTy = getTypeName(*MemberOrBase, IdLoc, S, 0/*SS*/);
if (!BaseTy)
return Diag(IdLoc, diag::err_mem_init_not_member_or_class)
<< MemberOrBase << SourceRange(IdLoc, RParenLoc);
QualType BaseType = QualType::getFromOpaquePtr(BaseTy);
if (!BaseType->isRecordType())
return Diag(IdLoc, diag::err_base_init_does_not_name_class)
<< BaseType << SourceRange(IdLoc, RParenLoc);
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
// 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.
// 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) {
if (Context.getCanonicalType(BaseType).getUnqualifiedType() ==
Context.getCanonicalType(Base->getType()).getUnqualifiedType()) {
// We found a direct base of this type. That's what we're
// initializing.
DirectBaseSpec = &*Base;
break;
}
}
// 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)) {
for (BasePaths::paths_iterator Path = Paths.begin();
Path != Paths.end(); ++Path) {
if (Path->back().Base->isVirtual()) {
VirtualBaseSpec = Path->back().Base;
break;
}
}
}
}
// 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)
<< MemberOrBase << SourceRange(IdLoc, RParenLoc);
return new CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, NumArgs);
}
Chris Lattner
committed
void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
Anders Carlsson
committed
SourceLocation ColonLoc,
MemInitTy **MemInits, unsigned NumMemInits) {
CXXConstructorDecl *Constructor =
Chris Lattner
committed
dyn_cast<CXXConstructorDecl>(ConstructorDecl.getAs<Decl>());
Anders Carlsson
committed
if (!Constructor) {
Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
return;
}
}
Anders Carlsson
committed
namespace {
/// PureVirtualMethodCollector - traverses a class and its superclasses
/// and determines if it has any pure virtual methods.
class VISIBILITY_HIDDEN PureVirtualMethodCollector {
ASTContext &Context;
Sebastian Redl
committed
public:
Anders Carlsson
committed
typedef llvm::SmallVector<const CXXMethodDecl*, 8> MethodList;
Sebastian Redl
committed
private:
Anders Carlsson
committed
MethodList Methods;
void Collect(const CXXRecordDecl* RD, MethodList& Methods);
public:
PureVirtualMethodCollector(ASTContext &Ctx, const CXXRecordDecl* RD)
: Context(Ctx) {
MethodList List;
Collect(RD, List);
// 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]);
}
}
bool empty() const { return Methods.empty(); }
MethodList::const_iterator methods_begin() { return Methods.begin(); }
MethodList::const_iterator methods_end() { return Methods.end(); }
Anders Carlsson
committed
};
void PureVirtualMethodCollector::Collect(const CXXRecordDecl* RD,
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) {
if (const RecordType *RT = Base->getType()->getAsRecordType()) {
const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl());
Anders Carlsson
committed
if (BaseDecl && BaseDecl->isAbstract())
Collect(BaseDecl, Methods);
}
}
// Next, zero out any pure virtual methods that this class overrides.
for (size_t i = 0, e = Methods.size(); i != e; ++i) {
const CXXMethodDecl *VMD = dyn_cast_or_null<CXXMethodDecl>(Methods[i]);
if (!VMD)
continue;
DeclContext::lookup_const_iterator I, E;
for (llvm::tie(I, E) = RD->lookup(Context, VMD->getDeclName());
I != E; ++I) {
Anders Carlsson
committed
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*I)) {
if (Context.getCanonicalType(MD->getType()) ==
Context.getCanonicalType(VMD->getType())) {
// We did find a matching method, which means that this is not a
// pure virtual method in the current class. Zero it out.
Methods[i] = 0;
}
}
}
}
// Finally, add pure virtual methods from this class.
for (RecordDecl::decl_iterator i = RD->decls_begin(Context),
e = RD->decls_end(Context);
Anders Carlsson
committed
i != e; ++i) {
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*i)) {
if (MD->isPure())
Methods.push_back(MD);
}
}
}
}
bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
Anders Carlsson
committed
unsigned DiagID, AbstractDiagSelID SelID,
const CXXRecordDecl *CurrentRD) {
if (!getLangOptions().CPlusPlus)
return false;
Anders Carlsson
committed
if (const ArrayType *AT = Context.getAsArrayType(T))
Anders Carlsson
committed
return RequireNonAbstractType(Loc, AT->getElementType(), DiagID, SelID,
CurrentRD);
if (const PointerType *PT = T->getAsPointerType()) {
// Find the innermost pointer type.
while (const PointerType *T = PT->getPointeeType()->getAsPointerType())
PT = T;
if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType()))
Anders Carlsson
committed
return RequireNonAbstractType(Loc, AT->getElementType(), DiagID, SelID,
CurrentRD);
const RecordType *RT = T->getAsRecordType();
if (!RT)
return false;
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
if (!RD)
return false;
Anders Carlsson
committed
if (CurrentRD && CurrentRD != RD)
return false;
if (!RD->isAbstract())
return false;
Diag(Loc, DiagID) << RD->getDeclName() << SelID;
// Check if we've already emitted the list of pure virtual functions for this
// class.
if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD))
return true;
PureVirtualMethodCollector Collector(Context, RD);
for (PureVirtualMethodCollector::MethodList::const_iterator I =
Collector.methods_begin(), E = Collector.methods_end(); I != E; ++I) {
const CXXMethodDecl *MD = *I;
Diag(MD->getLocation(), diag::note_pure_virtual_function) <<
MD->getDeclName();
}
if (!PureVirtualClassDiagSet)
PureVirtualClassDiagSet.reset(new RecordDeclSetTy);
PureVirtualClassDiagSet->insert(RD);
return true;
}
namespace {
class VISIBILITY_HIDDEN AbstractClassUsageDiagnoser
: public DeclVisitor<AbstractClassUsageDiagnoser, bool> {
Sema &SemaRef;
CXXRecordDecl *AbstractClass;
Anders Carlsson
committed
bool VisitDeclContext(const DeclContext *DC) {
bool Invalid = false;
for (CXXRecordDecl::decl_iterator I = DC->decls_begin(SemaRef.Context),
E = DC->decls_end(SemaRef.Context); I != E; ++I)
Invalid |= Visit(*I);
Anders Carlsson
committed
return Invalid;
}
Anders Carlsson
committed
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.
// because that requires
return VisitDeclContext(FD);
}
// Check the return type.
Anders Carlsson
committed
QualType RTy = FD->getType()->getAsFunctionType()->getResultType();
bool Invalid =
Anders Carlsson
committed
SemaRef.RequireNonAbstractType(FD->getLocation(), RTy,
diag::err_abstract_type_in_decl,
Anders Carlsson
committed
Sema::AbstractReturnType,
AbstractClass);
Anders Carlsson
committed
for (FunctionDecl::param_const_iterator I = FD->param_begin(),
E = FD->param_end(); I != E; ++I) {
const ParmVarDecl *VD = *I;
Invalid |=
SemaRef.RequireNonAbstractType(VD->getLocation(),
VD->getOriginalType(),
diag::err_abstract_type_in_decl,
Anders Carlsson
committed
Sema::AbstractParamType,
AbstractClass);
}
return Invalid;
}
Anders Carlsson
committed
bool VisitDecl(const Decl* D) {
if (const DeclContext *DC = dyn_cast<DeclContext>(D))
return VisitDeclContext(DC);
return false;
}
};
}
void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
Chris Lattner
committed
DeclPtrTy TagDecl,
SourceLocation LBrac,
SourceLocation RBrac) {
TemplateDecl *Template = AdjustDeclIfTemplate(TagDecl);
Chris Lattner
committed
(DeclPtrTy*)FieldCollector->getCurFields(),
FieldCollector->getCurNumFields(), LBrac, RBrac, 0);
Chris Lattner
committed
CXXRecordDecl *RD = cast<CXXRecordDecl>(TagDecl.getAs<Decl>());
Anders Carlsson
committed
if (!RD->isAbstract()) {
// Collect all the pure virtual methods and see if this is an abstract
// class after all.
PureVirtualMethodCollector Collector(Context, RD);
if (!Collector.empty())
RD->setAbstract(true);
}
Anders Carlsson
committed
if (RD->isAbstract())
AbstractClassUsageDiagnoser(*this, RD);
if (!Template)
Anders Carlsson
committed
AddImplicitlyDeclaredMembersToClass(RD);
/// 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) {
QualType ClassType = Context.getTypeDeclType(ClassDecl);
ClassType = Context.getCanonicalType(ClassType);
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.
DeclarationName Name
= Context.DeclarationNames.getCXXConstructorName(ClassType);
CXXConstructorDecl *DefaultCon =
CXXConstructorDecl::Create(Context, ClassDecl,
ClassDecl->getLocation(), Name,
Context.getFunctionType(Context.VoidTy,
0, 0, false, 0),
/*isExplicit=*/false,
/*isInline=*/true,
/*isImplicitlyDeclared=*/true);
DefaultCon->setAccess(AS_public);
DefaultCon->setImplicit();
ClassDecl->addDecl(Context, DefaultCon);
// Notify the class that we've added a constructor.
ClassDecl->addedConstructor(Context, DefaultCon);
}
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