diff options
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 2665 |
1 files changed, 2050 insertions, 615 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 75ceb19..acb2a67 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -12,18 +12,20 @@ //===----------------------------------------------------------------------===// #include "Sema.h" -#include "SemaInherit.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/TypeOrdering.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Basic/PartialDiagnostic.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/DeclSpec.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" #include <algorithm> // for std::equal #include <map> +#include <set> using namespace clang; @@ -37,13 +39,13 @@ namespace { /// 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 + class VISIBILITY_HIDDEN CheckDefaultArgumentVisitor : public StmtVisitor<CheckDefaultArgumentVisitor, bool> { Expr *DefaultArg; Sema *S; public: - CheckDefaultArgumentVisitor(Expr *defarg, Sema *s) + CheckDefaultArgumentVisitor(Expr *defarg, Sema *s) : DefaultArg(defarg), S(s) {} bool VisitExpr(Expr *Node); @@ -54,7 +56,7 @@ namespace { /// 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(), + for (Stmt::child_iterator I = Node->child_begin(), E = Node->child_end(); I != E; ++I) IsInvalid |= Visit(*I); return IsInvalid; @@ -74,7 +76,7 @@ namespace { // 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(), + 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)) { @@ -82,7 +84,7 @@ namespace { // Local variables shall not be used in default argument // expressions. if (VDecl->isBlockVarDecl()) - return S->Diag(DRE->getSourceRange().getBegin(), + return S->Diag(DRE->getSourceRange().getBegin(), diag::err_param_default_argument_references_local) << VDecl->getDeclName() << DefaultArg->getSourceRange(); } @@ -101,15 +103,48 @@ namespace { } } +bool +Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg, + SourceLocation EqualLoc) { + QualType ParamType = Param->getType(); + + if (RequireCompleteType(Param->getLocation(), Param->getType(), + diag::err_typecheck_decl_incomplete_type)) { + Param->setInvalidDecl(); + return true; + } + + Expr *Arg = (Expr *)DefaultArg.get(); + + // 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). + if (CheckInitializerTypes(Arg, ParamType, EqualLoc, + Param->getDeclName(), /*DirectInit=*/false)) + return true; + + Arg = MaybeCreateCXXExprWithTemporaries(Arg, /*DestroyTemps=*/false); + + // Okay: add the default argument to the parameter + Param->setDefaultArg(Arg); + + DefaultArg.release(); + + return false; +} + /// ActOnParamDefaultArgument - Check whether the default argument /// provided for a function parameter is well-formed. If so, attach it /// to the parameter declaration. void -Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc, +Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc, ExprArg defarg) { if (!param || !defarg.get()) return; - + ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>()); UnparsedDefaultArgLocs.erase(Param); @@ -124,25 +159,6 @@ Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc, 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); - } - if (DefaultInitFailed) { - return; - } - // Check that the default argument is well-formed CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg.get(), this); if (DefaultArgChecker.Visit(DefaultArg.get())) { @@ -150,27 +166,23 @@ Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc, return; } - DefaultArgPtr = MaybeCreateCXXExprWithTemporaries(DefaultArg.take(), - /*DestroyTemps=*/false); - - // Okay: add the default argument to the parameter - Param->setDefaultArg(DefaultArgPtr); + SetParamDefaultArgument(Param, move(DefaultArg), EqualLoc); } /// ActOnParamUnparsedDefaultArgument - We've seen a default /// argument for a function parameter, but we can't parse it yet /// because we're inside a class definition. Note that this default /// argument will be parsed later. -void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param, +void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc, SourceLocation ArgLoc) { if (!param) return; - + ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>()); if (Param) Param->setUnparsedDefaultArg(); - + UnparsedDefaultArgLocs[Param] = ArgLoc; } @@ -179,11 +191,11 @@ void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param, void Sema::ActOnParamDefaultArgumentError(DeclPtrTy param) { if (!param) return; - + ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>()); - + Param->setInvalidDecl(); - + UnparsedDefaultArgLocs.erase(Param); } @@ -230,7 +242,6 @@ 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 @@ -242,25 +253,97 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { // arguments supplied in this or previous declarations. A // default argument shall not be redefined by a later // declaration (not even to the same value). + // + // 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. 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(), + if (OldParam->hasDefaultArg() && NewParam->hasDefaultArg()) { + Diag(NewParam->getLocation(), diag::err_param_default_argument_redefinition) - << NewParam->getDefaultArg()->getSourceRange(); - Diag(OldParam->getLocation(), diag::note_previous_definition); + << 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(); Invalid = true; - } else if (OldParam->getDefaultArg()) { + } else if (OldParam->hasDefaultArg()) { // Merge the old default argument into the new parameter - NewParam->setDefaultArg(OldParam->getDefaultArg()); + if (OldParam->hasUninstantiatedDefaultArg()) + NewParam->setUninstantiatedDefaultArg( + OldParam->getUninstantiatedDefaultArg()); + else + NewParam->setDefaultArg(OldParam->getDefaultArg()); + } 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->getTemplateSpecializationKind() + != TSK_ImplicitInstantiation && + New->getTemplateSpecializationKind() != TSK_Undeclared) { + // C++ [temp.expr.spec]p21: + // Default function arguments shall not be specified in a declaration + // or a definition for one of the following explicit specializations: + // - the explicit specialization of a function template; + // - the explicit specialization of a member function template; + // - the explicit specialization of a member function of a class + // template where the class template specialization to which the + // member function specialization belongs is implicitly + // instantiated. + Diag(NewParam->getLocation(), diag::err_template_spec_default_arg) + << (New->getTemplateSpecializationKind() ==TSK_ExplicitSpecialization) + << New->getDeclName() + << NewParam->getDefaultArgRange(); + } 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(); + } } } if (CheckEquivalentExceptionSpec( - Old->getType()->getAsFunctionProtoType(), Old->getLocation(), - New->getType()->getAsFunctionProtoType(), New->getLocation())) { + Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(), + New->getType()->getAs<FunctionProtoType>(), New->getLocation())) { Invalid = true; } @@ -277,7 +360,7 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { // Find first parameter with a default argument for (p = 0; p < NumParams; ++p) { ParmVarDecl *Param = FD->getParamDecl(p); - if (Param->getDefaultArg()) + if (Param->hasDefaultArg()) break; } @@ -288,19 +371,19 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { // 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) { + for (; p < NumParams; ++p) { ParmVarDecl *Param = FD->getParamDecl(p); - if (!Param->getDefaultArg()) { + if (!Param->hasDefaultArg()) { if (Param->isInvalidDecl()) /* We already complained about this parameter. */; else if (Param->getIdentifier()) - Diag(Param->getLocation(), + Diag(Param->getLocation(), diag::err_param_default_argument_missing_name) << Param->getIdentifier(); else - Diag(Param->getLocation(), + Diag(Param->getLocation(), diag::err_param_default_argument_missing); - + LastMissingDefaultArg = p; } } @@ -329,7 +412,7 @@ bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, const CXXScopeSpec *SS) { CXXRecordDecl *CurDecl; if (SS && SS->isSet() && !SS->isInvalid()) { - DeclContext *DC = computeDeclContext(*SS); + DeclContext *DC = computeDeclContext(*SS, true); CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC); } else CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext); @@ -340,7 +423,7 @@ bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, return false; } -/// \brief Check the validity of a C++ base class specifier. +/// \brief Check the validity of a C++ base class specifier. /// /// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics /// and returns NULL otherwise. @@ -348,7 +431,7 @@ CXXBaseSpecifier * Sema::CheckBaseSpecifier(CXXRecordDecl *Class, SourceRange SpecifierRange, bool Virtual, AccessSpecifier Access, - QualType BaseType, + QualType BaseType, SourceLocation BaseLoc) { // C++ [class.union]p1: // A union shall not have base classes. @@ -359,7 +442,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, } if (BaseType->isDependentType()) - return new CXXBaseSpecifier(SpecifierRange, Virtual, + return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, Class->getTagKind() == RecordDecl::TK_class, Access, BaseType); @@ -379,16 +462,21 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, // 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)) + if (RequireCompleteType(BaseLoc, BaseType, + PDiag(diag::err_incomplete_base_class) + << SpecifierRange)) return 0; - // If the base class is polymorphic, the new one is, too. - RecordDecl *BaseDecl = BaseType->getAsRecordType()->getDecl(); + // If the base class is polymorphic or isn't empty, the new one is/isn't, too. + RecordDecl *BaseDecl = BaseType->getAs<RecordType>()->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()) + CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl); + assert(CXXBaseDecl && "Base type is not a C++ type"); + if (!CXXBaseDecl->isEmpty()) + Class->setEmpty(false); + if (CXXBaseDecl->isPolymorphic()) Class->setPolymorphic(true); // C++ [dcl.init.aggr]p1: @@ -400,33 +488,59 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, // C++ [class.ctor]p5: // A constructor is trivial if its class has no virtual base classes. Class->setHasTrivialConstructor(false); + + // 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); + + // 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); } else { // C++ [class.ctor]p5: - // A constructor is trivial if all the direct base classes of its + // A constructor is trivial if all the direct base classes of its // class have trivial constructors. - Class->setHasTrivialConstructor(cast<CXXRecordDecl>(BaseDecl)-> - hasTrivialConstructor()); + 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); } // C++ [class.ctor]p3: // A destructor is trivial if all the direct base classes of its class // have trivial destructors. - Class->setHasTrivialDestructor(cast<CXXRecordDecl>(BaseDecl)-> - hasTrivialDestructor()); - + if (!cast<CXXRecordDecl>(BaseDecl)->hasTrivialDestructor()) + Class->setHasTrivialDestructor(false); + // Create the base specifier. // FIXME: Allocate via ASTContext? - return new CXXBaseSpecifier(SpecifierRange, Virtual, - Class->getTagKind() == RecordDecl::TK_class, + return new (Context) 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 { +/// example: +/// class foo : public bar, virtual private baz { /// 'public bar' and 'virtual private baz' are each base-specifiers. -Sema::BaseResult +Sema::BaseResult Sema::ActOnBaseSpecifier(DeclPtrTy classdecl, SourceRange SpecifierRange, bool Virtual, AccessSpecifier Access, TypeTy *basetype, SourceLocation BaseLoc) { @@ -435,12 +549,12 @@ Sema::ActOnBaseSpecifier(DeclPtrTy classdecl, SourceRange SpecifierRange, AdjustDeclIfTemplate(classdecl); CXXRecordDecl *Class = cast<CXXRecordDecl>(classdecl.getAs<Decl>()); - QualType BaseType = QualType::getFromOpaquePtr(basetype); + QualType BaseType = GetTypeFromParser(basetype); if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange, Virtual, Access, BaseType, BaseLoc)) return BaseSpec; - + return true; } @@ -461,7 +575,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, unsigned NumGoodBases = 0; bool Invalid = false; for (unsigned idx = 0; idx < NumBases; ++idx) { - QualType NewBaseType + QualType NewBaseType = Context.getCanonicalType(Bases[idx]->getType()); NewBaseType = NewBaseType.getUnqualifiedType(); @@ -476,7 +590,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, // Delete the duplicate base class specifier; we're going to // overwrite its pointer later. - delete Bases[idx]; + Context.Deallocate(Bases[idx]); Invalid = true; } else { @@ -492,7 +606,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, // 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]; + Context.Deallocate(Bases[idx]); return Invalid; } @@ -500,7 +614,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, /// ActOnBaseSpecifiers - Attach the given base specifiers to the /// class, after checking whether there are any duplicate base /// classes. -void Sema::ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases, +void Sema::ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases, unsigned NumBases) { if (!ClassDecl || !Bases || !NumBases) return; @@ -510,6 +624,139 @@ void Sema::ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases, (CXXBaseSpecifier**)(Bases), NumBases); } +/// \brief Determine whether the type \p Derived is a C++ class that is +/// derived from the type \p Base. +bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { + if (!getLangOptions().CPlusPlus) + return false; + + const RecordType *DerivedRT = Derived->getAs<RecordType>(); + if (!DerivedRT) + return false; + + const RecordType *BaseRT = Base->getAs<RecordType>(); + if (!BaseRT) + return false; + + CXXRecordDecl *DerivedRD = cast<CXXRecordDecl>(DerivedRT->getDecl()); + CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl()); + return DerivedRD->isDerivedFrom(BaseRD); +} + +/// \brief Determine whether the type \p Derived is a C++ class that is +/// derived from the type \p Base. +bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) { + if (!getLangOptions().CPlusPlus) + return false; + + const RecordType *DerivedRT = Derived->getAs<RecordType>(); + if (!DerivedRT) + return false; + + const RecordType *BaseRT = Base->getAs<RecordType>(); + if (!BaseRT) + return false; + + CXXRecordDecl *DerivedRD = cast<CXXRecordDecl>(DerivedRT->getDecl()); + CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl()); + return DerivedRD->isDerivedFrom(BaseRD, Paths); +} + +/// CheckDerivedToBaseConversion - Check whether the Derived-to-Base +/// conversion (where Derived and Base are class types) is +/// well-formed, meaning that the conversion is unambiguous (and +/// that all of the base classes are accessible). Returns true +/// and emits a diagnostic if the code is ill-formed, returns false +/// otherwise. Loc is the location where this routine should point to +/// if there is an error, and Range is the source range to highlight +/// if there is an error. +bool +Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, + unsigned InaccessibleBaseID, + unsigned AmbigiousBaseConvID, + SourceLocation Loc, SourceRange Range, + DeclarationName Name) { + // First, determine whether the path from Derived to Base is + // ambiguous. This is slightly more expensive than checking whether + // the Derived to Base conversion exists, because here we need to + // explore multiple paths to determine if there is an ambiguity. + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + bool DerivationOkay = IsDerivedFrom(Derived, Base, Paths); + assert(DerivationOkay && + "Can only be used with a derived-to-base conversion"); + (void)DerivationOkay; + + if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) { + // Check that the base class can be accessed. + return CheckBaseClassAccess(Derived, Base, InaccessibleBaseID, Paths, Loc, + Name); + } + + // We know that the derived-to-base conversion is ambiguous, and + // we're going to produce a diagnostic. Perform the derived-to-base + // search just one more time to compute all of the possible paths so + // that we can print them out. This is more expensive than any of + // the previous derived-to-base checks we've done, but at this point + // performance isn't as much of an issue. + Paths.clear(); + Paths.setRecordingPaths(true); + bool StillOkay = IsDerivedFrom(Derived, Base, Paths); + assert(StillOkay && "Can only be used with a derived-to-base conversion"); + (void)StillOkay; + + // Build up a textual representation of the ambiguous paths, e.g., + // D -> B -> A, that will be used to illustrate the ambiguous + // conversions in the diagnostic. We only print one of the paths + // to each base class subobject. + std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths); + + Diag(Loc, AmbigiousBaseConvID) + << Derived << Base << PathDisplayStr << Range << Name; + return true; +} + +bool +Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, + SourceLocation Loc, SourceRange Range) { + return CheckDerivedToBaseConversion(Derived, Base, + diag::err_conv_to_inaccessible_base, + diag::err_ambiguous_derived_to_base_conv, + Loc, Range, DeclarationName()); +} + + +/// @brief Builds a string representing ambiguous paths from a +/// specific derived class to different subobjects of the same base +/// class. +/// +/// This function builds a string that can be used in error messages +/// to show the different paths that one can take through the +/// inheritance hierarchy to go from the derived class to different +/// subobjects of a base class. The result looks something like this: +/// @code +/// struct D -> struct B -> struct A +/// struct D -> struct C -> struct A +/// @endcode +std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) { + std::string PathDisplayStr; + std::set<unsigned> DisplayedPaths; + for (CXXBasePaths::paths_iterator Path = Paths.begin(); + Path != Paths.end(); ++Path) { + if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) { + // We haven't displayed a path to this particular base + // class subobject yet. + PathDisplayStr += "\n "; + PathDisplayStr += Context.getTypeDeclType(Paths.getOrigin()).getAsString(); + for (CXXBasePath::const_iterator Element = Path->begin(); + Element != Path->end(); ++Element) + PathDisplayStr += " -> " + Element->Base->getType().getAsString(); + } + } + + return PathDisplayStr; +} + //===----------------------------------------------------------------------===// // C++ class member Handling //===----------------------------------------------------------------------===// @@ -520,6 +767,7 @@ void Sema::ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases, /// any. Sema::DeclPtrTy Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, + MultiTemplateParamsArg TemplateParameterLists, ExprTy *BW, ExprTy *InitExpr, bool Deleted) { const DeclSpec &DS = D.getDeclSpec(); DeclarationName Name = GetNameForDeclarator(D); @@ -529,6 +777,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, bool isFunc = D.isFunctionDeclarator(); + assert(!DS.isFriendSpecified()); + // 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 @@ -546,7 +796,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_function); else Diag(DS.getThreadSpecLoc(), diag::err_mutable_function); - + // FIXME: It would be nicer if the keyword was ignored only for this // declarator. Otherwise we could get follow-up errors. D.getMutableDeclSpec().ClearStorageClassSpecs(); @@ -585,7 +835,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, // typedef int f(); // f a; // - QualType TDType = QualType::getFromOpaquePtr(DS.getTypeRep()); + QualType TDType = GetTypeFromParser(DS.getTypeRep()); isFunc = TDType->isFunctionType(); } @@ -595,11 +845,13 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, Decl *Member; if (isInstField) { + // FIXME: Check for template parameters! Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth, AS); assert(Member && "HandleField never returns null"); } else { - Member = ActOnDeclarator(S, D).getAs<Decl>(); + Member = HandleDeclarator(S, D, move(TemplateParameterLists), false) + .getAs<Decl>(); if (!Member) { if (BitWidth) DeleteExpr(BitWidth); return DeclPtrTy(); @@ -622,16 +874,21 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, // 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() + << Name << cast<ValueDecl>(Member)->getType() << BitWidth->getSourceRange(); } - + DeleteExpr(BitWidth); BitWidth = 0; Member->setInvalidDecl(); } Member->setAccess(AS); + + // 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); } assert((Name || isInstField) && "No identifier for non-field ?"); @@ -649,7 +906,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, } /// ActOnMemInitializer - Handle a C++ member initializer. -Sema::MemInitResult +Sema::MemInitResult Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, Scope *S, const CXXScopeSpec &SS, @@ -662,8 +919,10 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, SourceLocation RParenLoc) { if (!ConstructorD) return true; - - CXXConstructorDecl *Constructor + + AdjustDeclIfTemplate(ConstructorD); + + CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD.getAs<Decl>()); if (!Constructor) { // The user wrote a constructor initializer on a function that is @@ -688,141 +947,657 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, if (!SS.getScopeRep() && !TemplateTypeTy) { // Look for a member, first. FieldDecl *Member = 0; - DeclContext::lookup_result Result + DeclContext::lookup_result Result = ClassDecl->lookup(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, - IdLoc); - } + if (Member) + return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc, + RParenLoc); } // It didn't name a member, so see if it names a class. - TypeTy *BaseTy = TemplateTypeTy ? TemplateTypeTy + TypeTy *BaseTy = TemplateTypeTy ? TemplateTypeTy : getTypeName(*MemberOrBase, IdLoc, S, &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() && !BaseType->isDependentType()) - 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. - - // 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; + QualType BaseType = GetTypeFromParser(BaseTy); + + 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. + } else if (FieldType->getAs<RecordType>()) { + 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(); + } } + } else if (NumArgs != 1 && NumArgs != 0) { + return Diag(IdLoc, diag::err_mem_initializer_mismatch) + << Member->getDeclName() << SourceRange(IdLoc, RParenLoc); + } else if (!HasDependentArg) { + Expr *NewExp; + if (NumArgs == 0) { + if (FieldType->isReferenceType()) { + Diag(IdLoc, diag::err_null_intialized_reference_member) + << Member->getDeclName(); + return Diag(Member->getLocation(), diag::note_declared_at); + } + NewExp = new (Context) CXXZeroInitValueExpr(FieldType, IdLoc, RParenLoc); + NumArgs = 1; + } + else + NewExp = (Expr*)Args[0]; + if (PerformCopyInitialization(NewExp, FieldType, "passing")) + return true; + Args[0] = NewExp; } - - // 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; + // FIXME: Perform direct initialization of the member. + return new (Context) CXXBaseOrMemberInitializer(Member, (Expr **)Args, + NumArgs, C, IdLoc, RParenLoc); +} + +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. + + // 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. + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + if (IsDerivedFrom(Context.getTypeDeclType(ClassDecl), BaseType, Paths)) { + for (CXXBasePaths::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) + << 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); } - // 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); - // 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); - + CXXConstructorDecl *C = 0; + if (!BaseType->isDependentType() && !HasDependentArg) { + DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(BaseType)); + ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); + + C = PerformInitializationByConstructor(BaseType, + MultiExprArg(*this, + (void**)Args, NumArgs), + IdLoc, SourceRange(IdLoc, RParenLoc), + Name, IK_Direct, + ConstructorArgs); + if (C) { + // Take over the constructor arguments as our own. + NumArgs = ConstructorArgs.size(); + Args = (Expr **)ConstructorArgs.take(); + } + } + + return new (Context) CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, + NumArgs, C, IdLoc, RParenLoc); +} + +void +Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor, + CXXBaseOrMemberInitializer **Initializers, + unsigned NumInitializers, + llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases, + 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; + + 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; + } + } + + if (HasDependentBaseInit) { + // FIXME. This does not preserve the ordering of the initializers. + // Try (with -Wreorder) + // template<class X> struct A {}; + // template<class X> struct B : A<X> { + // B() : x1(10), A<X>() {} + // 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. + + // 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; + if (CXXBaseOrMemberInitializer *Value = + AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) { + CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); + assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null"); + if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context)) + MarkDeclarationReferenced(Value->getSourceLocation(), Ctor); + AllToInit.push_back(Value); + } + else { + CXXRecordDecl *VBaseDecl = + cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); + assert(VBaseDecl && "setBaseOrMemberInitializers - VBaseDecl null"); + CXXConstructorDecl *Ctor = VBaseDecl->getDefaultConstructor(Context); + if (!Ctor) + Bases.push_back(VBase); + else + MarkDeclarationReferenced(Constructor->getLocation(), Ctor); + + CXXBaseOrMemberInitializer *Member = + new (Context) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0, + Ctor, + SourceLocation(), + SourceLocation()); + AllToInit.push_back(Member); + } + } + + 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; + if (CXXBaseOrMemberInitializer *Value = + AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) { + CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null"); + if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context)) + MarkDeclarationReferenced(Value->getSourceLocation(), Ctor); + AllToInit.push_back(Value); + } + else { + CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null"); + CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context); + if (!Ctor) + Bases.push_back(Base); + else + MarkDeclarationReferenced(Constructor->getLocation(), Ctor); + + CXXBaseOrMemberInitializer *Member = + new (Context) CXXBaseOrMemberInitializer(Base->getType(), 0, 0, + BaseDecl->getDefaultConstructor(Context), + SourceLocation(), + SourceLocation()); + AllToInit.push_back(Member); + } + } + } + + // non-static data members. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + E = ClassDecl->field_end(); Field != E; ++Field) { + if ((*Field)->isAnonymousStructOrUnion()) { + if (const RecordType *FieldClassType = + Field->getType()->getAs<RecordType>()) { + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(), + 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)) { + QualType FT = (*Field)->getType(); + if (const RecordType* RT = FT->getAs<RecordType>()) { + CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RT->getDecl()); + assert(FieldRecDecl && "setBaseOrMemberInitializers - BaseDecl null"); + if (CXXConstructorDecl *Ctor = + FieldRecDecl->getDefaultConstructor(Context)) + MarkDeclarationReferenced(Value->getSourceLocation(), Ctor); + } + AllToInit.push_back(Value); + continue; + } + + 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); + CXXBaseOrMemberInitializer *Member = + new (Context) CXXBaseOrMemberInitializer((*Field), 0, 0, + Ctor, + SourceLocation(), + SourceLocation()); + AllToInit.push_back(Member); + if (Ctor) + MarkDeclarationReferenced(Constructor->getLocation(), Ctor); + 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); + } + } + + NumInitializers = AllToInit.size(); + if (NumInitializers > 0) { + Constructor->setNumBaseOrMemberInitializers(NumInitializers); + CXXBaseOrMemberInitializer **baseOrMemberInitializers = + new (Context) CXXBaseOrMemberInitializer*[NumInitializers]; + + Constructor->setBaseOrMemberInitializers(baseOrMemberInitializers); + for (unsigned Idx = 0; Idx < NumInitializers; ++Idx) + baseOrMemberInitializers[Idx] = AllToInit[Idx]; + } +} + +void +Sema::BuildBaseOrMemberInitializers(ASTContext &C, + CXXConstructorDecl *Constructor, + CXXBaseOrMemberInitializer **Initializers, + unsigned NumInitializers + ) { + llvm::SmallVector<CXXBaseSpecifier *, 4>Bases; + llvm::SmallVector<FieldDecl *, 4>Members; + + setBaseOrMemberInitializers(Constructor, + Initializers, NumInitializers, Bases, Members); + for (unsigned int i = 0; i < Bases.size(); i++) + Diag(Bases[i]->getSourceRange().getBegin(), + diag::err_missing_default_constructor) << 0 << Bases[i]->getType(); + for (unsigned int i = 0; i < Members.size(); i++) + Diag(Members[i]->getLocation(), diag::err_missing_default_constructor) + << 1 << Members[i]->getType(); +} + +static void *GetKeyForTopLevelField(FieldDecl *Field) { + // For anonymous unions, use the class declaration as the key. + if (const RecordType *RT = Field->getType()->getAs<RecordType>()) { + if (RT->getDecl()->isAnonymousStructOrUnion()) + return static_cast<void *>(RT->getDecl()); + } + return static_cast<void *>(Field); +} + +static void *GetKeyForBase(QualType BaseType) { + if (const RecordType *RT = BaseType->getAs<RecordType>()) + return (void *)RT; + + assert(0 && "Unexpected base type!"); + return 0; +} - return new CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, NumArgs, - IdLoc); +static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member, + bool MemberMaybeAnon = false) { + // For fields injected into the class via declaration of an anonymous union, + // use its anonymous union class declaration as the unique key. + if (Member->isMemberInitializer()) { + FieldDecl *Field = Member->getMember(); + + // After BuildBaseOrMemberInitializers call, Field is the anonymous union + // data member of the class. Data member used in the initializer list is + // in AnonUnionMember field. + if (MemberMaybeAnon && Field->isAnonymousStructOrUnion()) + Field = Member->getAnonUnionMember(); + if (Field->getDeclContext()->isRecord()) { + RecordDecl *RD = cast<RecordDecl>(Field->getDeclContext()); + if (RD->isAnonymousStructOrUnion()) + return static_cast<void *>(RD); + } + return static_cast<void *>(Field); + } + + return GetKeyForBase(QualType(Member->getBaseClass(), 0)); } -void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, +void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, SourceLocation ColonLoc, MemInitTy **MemInits, unsigned NumMemInits) { if (!ConstructorDecl) return; - - CXXConstructorDecl *Constructor + + AdjustDeclIfTemplate(ConstructorDecl); + + CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorDecl.getAs<Decl>()); - + if (!Constructor) { Diag(ColonLoc, diag::err_only_constructors_take_base_inits); return; } - llvm::DenseMap<void*, CXXBaseOrMemberInitializer *>Members; - bool err = false; + + if (!Constructor->isDependentContext()) { + llvm::DenseMap<void*, CXXBaseOrMemberInitializer *>Members; + bool err = false; + for (unsigned i = 0; i < NumMemInits; i++) { + CXXBaseOrMemberInitializer *Member = + static_cast<CXXBaseOrMemberInitializer*>(MemInits[i]); + void *KeyToMember = GetKeyForMember(Member); + CXXBaseOrMemberInitializer *&PrevMember = Members[KeyToMember]; + if (!PrevMember) { + PrevMember = Member; + continue; + } + if (FieldDecl *Field = Member->getMember()) + Diag(Member->getSourceLocation(), + diag::error_multiple_mem_initialization) + << Field->getNameAsString(); + else { + Type *BaseClass = Member->getBaseClass(); + assert(BaseClass && "ActOnMemInitializers - neither field or base"); + Diag(Member->getSourceLocation(), + diag::error_multiple_base_initialization) + << QualType(BaseClass, 0); + } + Diag(PrevMember->getSourceLocation(), diag::note_previous_initializer) + << 0; + err = true; + } + + if (err) + return; + } + + BuildBaseOrMemberInitializers(Context, Constructor, + reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits), + NumMemInits); + + if (Constructor->isDependentContext()) + return; + + if (Diags.getDiagnosticLevel(diag::warn_base_initialized) == + Diagnostic::Ignored && + Diags.getDiagnosticLevel(diag::warn_field_initialized) == + Diagnostic::Ignored) + return; + + // 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; + + 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) + AllBaseOrMembers.push_back(GetKeyForBase(VBase->getType())); + + 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; + AllBaseOrMembers.push_back(GetKeyForBase(Base->getType())); + } + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + E = ClassDecl->field_end(); Field != E; ++Field) + AllBaseOrMembers.push_back(GetKeyForTopLevelField(*Field)); + + int Last = AllBaseOrMembers.size(); + int curIndex = 0; + CXXBaseOrMemberInitializer *PrevMember = 0; for (unsigned i = 0; i < NumMemInits; i++) { - CXXBaseOrMemberInitializer *Member = + CXXBaseOrMemberInitializer *Member = static_cast<CXXBaseOrMemberInitializer*>(MemInits[i]); - void *KeyToMember = Member->getBaseOrMember(); - // For fields injected into the class via declaration of an anonymous union, - // use its anonymous union class declaration as the unique key. - if (FieldDecl *Field = Member->getMember()) - if (Field->getDeclContext()->isRecord() && - cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion()) - KeyToMember = static_cast<void *>(Field->getDeclContext()); - CXXBaseOrMemberInitializer *&PrevMember = Members[KeyToMember]; - if (!PrevMember) { - PrevMember = Member; - continue; + 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(), + diag::warn_base_initialized) + << QualType(BaseClass, 0); + } else { + FieldDecl *Field = PrevMember->getMember(); + Diag(PrevMember->getSourceLocation(), + diag::warn_field_initialized) + << Field->getNameAsString(); + } + // Also the note! + if (FieldDecl *Field = Member->getMember()) + Diag(Member->getSourceLocation(), + diag::note_fieldorbase_initialized_here) << 0 + << Field->getNameAsString(); + else { + Type *BaseClass = Member->getBaseClass(); + Diag(Member->getSourceLocation(), + diag::note_fieldorbase_initialized_here) << 1 + << QualType(BaseClass, 0); + } + for (curIndex = 0; curIndex < Last; curIndex++) + if (MemberInCtorList == AllBaseOrMembers[curIndex]) + break; } - if (FieldDecl *Field = Member->getMember()) - Diag(Member->getSourceLocation(), - diag::error_multiple_mem_initialization) - << Field->getNameAsString(); - else { - Type *BaseClass = Member->getBaseClass(); - assert(BaseClass && "ActOnMemInitializers - neither field or base"); - Diag(Member->getSourceLocation(), - diag::error_multiple_base_initialization) - << BaseClass->getDesugaredType(true); + PrevMember = Member; + } +} + +void +Sema::computeBaseOrMembersToDestroy(CXXDestructorDecl *Destructor) { + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Destructor->getDeclContext()); + llvm::SmallVector<uintptr_t, 32> AllToDestruct; + + 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)) + MarkDeclarationReferenced(Destructor->getLocation(), + const_cast<CXXDestructorDecl*>(Dtor)); + + uintptr_t Member = + reinterpret_cast<uintptr_t>(VBase->getType().getTypePtr()) + | 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)) + MarkDeclarationReferenced(Destructor->getLocation(), + const_cast<CXXDestructorDecl*>(Dtor)); + uintptr_t Member = + reinterpret_cast<uintptr_t>(Base->getType().getTypePtr()) + | CXXDestructorDecl::DRCTNONVBASE; + AllToDestruct.push_back(Member); + } + + // 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()); + + 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; + if (const CXXDestructorDecl *Dtor = + FieldClassDecl->getDestructor(Context)) + MarkDeclarationReferenced(Destructor->getLocation(), + const_cast<CXXDestructorDecl*>(Dtor)); + uintptr_t Member = reinterpret_cast<uintptr_t>(*Field); + AllToDestruct.push_back(Member); } - Diag(PrevMember->getSourceLocation(), diag::note_previous_initializer) - << 0; - err = true; } - if (!err) - Constructor->setBaseOrMemberInitializers(Context, - reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits), - NumMemInits); + + unsigned NumDestructions = AllToDestruct.size(); + if (NumDestructions > 0) { + Destructor->setNumBaseOrMemberDestructions(NumDestructions); + uintptr_t *BaseOrMemberDestructions = + 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); + } +} + +void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) { + if (!CDtorDecl) + return; + + AdjustDeclIfTemplate(CDtorDecl); + + if (CXXConstructorDecl *Constructor + = dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>())) + BuildBaseOrMemberInitializers(Context, + Constructor, + (CXXBaseOrMemberInitializer **)0, 0); } namespace { @@ -836,58 +1611,58 @@ namespace { private: MethodList Methods; - + void Collect(const CXXRecordDecl* RD, MethodList& Methods); - + public: - PureVirtualMethodCollector(ASTContext &Ctx, const CXXRecordDecl* RD) + 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(); } }; - - void PureVirtualMethodCollector::Collect(const CXXRecordDecl* RD, + + 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()) { + if (const RecordType *RT = Base->getType()->getAs<RecordType>()) { const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl()); if (BaseDecl && BaseDecl->isAbstract()) Collect(BaseDecl, Methods); } } - + // Next, zero out any pure virtual methods that this class overrides. typedef llvm::SmallPtrSet<const CXXMethodDecl*, 4> MethodSetTy; - + MethodSetTy OverriddenMethods; size_t MethodsSize = Methods.size(); - for (RecordDecl::decl_iterator i = RD->decls_begin(), e = RD->decls_end(); + for (RecordDecl::decl_iterator i = RD->decls_begin(), e = RD->decls_end(); i != e; ++i) { // Traverse the record, looking for methods. if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*i)) { - // If the method is pre virtual, add it to the methods vector. + // If the method is pure virtual, add it to the methods vector. if (MD->isPure()) { Methods.push_back(MD); continue; } - + // 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) { @@ -896,82 +1671,92 @@ namespace { } } } - - // Now go through the methods and zero out all the ones we know are + + // Now go through the methods and zero out all the ones we know are // overridden. for (size_t i = 0, e = MethodsSize; i != e; ++i) { if (OverriddenMethods.count(Methods[i])) Methods[i] = 0; } - + } } -bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, + +bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID, AbstractDiagSelID SelID, const CXXRecordDecl *CurrentRD) { - + if (SelID == -1) + return RequireNonAbstractType(Loc, T, + PDiag(DiagID), CurrentRD); + else + return RequireNonAbstractType(Loc, T, + PDiag(DiagID) << SelID, CurrentRD); +} + +bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, + const PartialDiagnostic &PD, + const CXXRecordDecl *CurrentRD) { if (!getLangOptions().CPlusPlus) return false; - + if (const ArrayType *AT = Context.getAsArrayType(T)) - return RequireNonAbstractType(Loc, AT->getElementType(), DiagID, SelID, + return RequireNonAbstractType(Loc, AT->getElementType(), PD, CurrentRD); - - if (const PointerType *PT = T->getAsPointerType()) { + + if (const PointerType *PT = T->getAs<PointerType>()) { // Find the innermost pointer type. - while (const PointerType *T = PT->getPointeeType()->getAsPointerType()) + while (const PointerType *T = PT->getPointeeType()->getAs<PointerType>()) PT = T; - + if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType())) - return RequireNonAbstractType(Loc, AT->getElementType(), DiagID, SelID, - CurrentRD); + return RequireNonAbstractType(Loc, AT->getElementType(), PD, CurrentRD); } - - const RecordType *RT = T->getAsRecordType(); + + const RecordType *RT = T->getAs<RecordType>(); if (!RT) return false; - + const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); if (!RD) return false; if (CurrentRD && CurrentRD != RD) return false; - + if (!RD->isAbstract()) return false; - - Diag(Loc, DiagID) << RD->getDeclName() << SelID; - + + Diag(Loc, PD) << RD->getDeclName(); + // 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 = + + 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) << + + 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 + class VISIBILITY_HIDDEN AbstractClassUsageDiagnoser : public DeclVisitor<AbstractClassUsageDiagnoser, bool> { Sema &SemaRef; CXXRecordDecl *AbstractClass; - + bool VisitDeclContext(const DeclContext *DC) { bool Invalid = false; @@ -981,7 +1766,7 @@ namespace { return Invalid; } - + public: AbstractClassUsageDiagnoser(Sema& SemaRef, CXXRecordDecl *ac) : SemaRef(SemaRef), AbstractClass(ac) { @@ -992,36 +1777,36 @@ namespace { 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 + // because that requires return VisitDeclContext(FD); } - + // Check the return type. - QualType RTy = FD->getType()->getAsFunctionType()->getResultType(); - bool Invalid = + QualType RTy = FD->getType()->getAs<FunctionType>()->getResultType(); + bool Invalid = SemaRef.RequireNonAbstractType(FD->getLocation(), RTy, diag::err_abstract_type_in_decl, Sema::AbstractReturnType, AbstractClass); - for (FunctionDecl::param_const_iterator I = FD->param_begin(), + for (FunctionDecl::param_const_iterator I = FD->param_begin(), E = FD->param_end(); I != E; ++I) { const ParmVarDecl *VD = *I; - Invalid |= + Invalid |= SemaRef.RequireNonAbstractType(VD->getLocation(), - VD->getOriginalType(), - diag::err_abstract_type_in_decl, + VD->getOriginalType(), + diag::err_abstract_type_in_decl, Sema::AbstractParamType, AbstractClass); } return Invalid; } - + bool VisitDecl(const Decl* D) { if (const DeclContext *DC = dyn_cast<DeclContext>(D)) return VisitDeclContext(DC); - + return false; } }; @@ -1033,7 +1818,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, SourceLocation RBrac) { if (!TagDecl) return; - + AdjustDeclIfTemplate(TagDecl); ActOnFields(S, RLoc, TagDecl, (DeclPtrTy*)FieldCollector->getCurFields(), @@ -1044,37 +1829,13 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, // Collect all the pure virtual methods and see if this is an abstract // class after all. PureVirtualMethodCollector Collector(Context, RD); - if (!Collector.empty()) + if (!Collector.empty()) RD->setAbstract(true); } - - if (RD->isAbstract()) + + if (RD->isAbstract()) AbstractClassUsageDiagnoser(*this, RD); - - if (RD->hasTrivialConstructor() || RD->hasTrivialDestructor()) { - for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); - i != e; ++i) { - // All the nonstatic data members must have trivial constructors. - QualType FTy = i->getType(); - while (const ArrayType *AT = Context.getAsArrayType(FTy)) - FTy = AT->getElementType(); - - if (const RecordType *RT = FTy->getAsRecordType()) { - CXXRecordDecl *FieldRD = cast<CXXRecordDecl>(RT->getDecl()); - - if (!FieldRD->hasTrivialConstructor()) - RD->setHasTrivialConstructor(false); - if (!FieldRD->hasTrivialDestructor()) - RD->setHasTrivialDestructor(false); - - // If RD has neither a trivial constructor nor a trivial destructor - // we don't need to continue checking. - if (!RD->hasTrivialConstructor() && !RD->hasTrivialDestructor()) - break; - } - } - } - + if (!RD->isDependentType()) AddImplicitlyDeclaredMembersToClass(RD); } @@ -1085,8 +1846,8 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, /// [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); + CanQualType ClassType + = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); // FIXME: Implicit declarations have exception specifications, which are // the union of the specifications of the implicitly called functions. @@ -1098,18 +1859,20 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { // 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 + DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(ClassType); - CXXConstructorDecl *DefaultCon = + CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name, Context.getFunctionType(Context.VoidTy, 0, 0, false, 0), + /*DInfo=*/0, /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true); DefaultCon->setAccess(AS_public); DefaultCon->setImplicit(); + DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor()); ClassDecl->addDecl(DefaultCon); } @@ -1133,8 +1896,8 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); HasConstCopyConstructor && Base != ClassDecl->bases_end(); ++Base) { const CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl()); - HasConstCopyConstructor + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + HasConstCopyConstructor = BaseClassDecl->hasConstCopyConstructor(Context); } @@ -1148,10 +1911,10 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { QualType FieldType = (*Field)->getType(); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) FieldType = Array->getElementType(); - if (const RecordType *FieldClassType = FieldType->getAsRecordType()) { - const CXXRecordDecl *FieldClassDecl + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + const CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(FieldClassType->getDecl()); - HasConstCopyConstructor + HasConstCopyConstructor = FieldClassDecl->hasConstCopyConstructor(Context); } } @@ -1167,7 +1930,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { // An implicitly-declared copy constructor is an inline public // member of its class. - DeclarationName Name + DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(ClassType); CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create(Context, ClassDecl, @@ -1175,17 +1938,20 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { Context.getFunctionType(Context.VoidTy, &ArgType, 1, false, 0), + /*DInfo=*/0, /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true); CopyConstructor->setAccess(AS_public); CopyConstructor->setImplicit(); + CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor()); // Add the parameter to the constructor. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor, ClassDecl->getLocation(), /*IdentifierInfo=*/0, - ArgType, VarDecl::None, 0); + ArgType, /*DInfo=*/0, + VarDecl::None, 0); CopyConstructor->setParams(Context, &FromParam, 1); ClassDecl->addDecl(CopyConstructor); } @@ -1213,8 +1979,10 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); HasConstCopyAssignment && Base != ClassDecl->bases_end(); ++Base) { const CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl()); - HasConstCopyAssignment = BaseClassDecl->hasConstCopyAssignment(Context); + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + const CXXMethodDecl *MD = 0; + HasConstCopyAssignment = BaseClassDecl->hasConstCopyAssignment(Context, + MD); } // -- for all the nonstatic data members of X that are of a class @@ -1227,11 +1995,12 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { QualType FieldType = (*Field)->getType(); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) FieldType = Array->getElementType(); - if (const RecordType *FieldClassType = FieldType->getAsRecordType()) { + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { const CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(FieldClassType->getDecl()); + const CXXMethodDecl *MD = 0; HasConstCopyAssignment - = FieldClassDecl->hasConstCopyAssignment(Context); + = FieldClassDecl->hasConstCopyAssignment(Context, MD); } } @@ -1253,15 +2022,18 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { CXXMethodDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name, Context.getFunctionType(RetType, &ArgType, 1, false, 0), - /*isStatic=*/false, /*isInline=*/true); + /*DInfo=*/0, /*isStatic=*/false, /*isInline=*/true); CopyAssignment->setAccess(AS_public); CopyAssignment->setImplicit(); + CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment()); + CopyAssignment->setCopyAssignment(true); // Add the parameter to the operator. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, ClassDecl->getLocation(), /*IdentifierInfo=*/0, - ArgType, VarDecl::None, 0); + ArgType, /*DInfo=*/0, + VarDecl::None, 0); CopyAssignment->setParams(Context, &FromParam, 1); // Don't call addedAssignmentOperator. There is no way to distinguish an @@ -1274,9 +2046,9 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { // 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. - DeclarationName Name + DeclarationName Name = Context.DeclarationNames.getCXXDestructorName(ClassType); - CXXDestructorDecl *Destructor + CXXDestructorDecl *Destructor = CXXDestructorDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name, Context.getFunctionType(Context.VoidTy, @@ -1285,16 +2057,25 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { /*isImplicitlyDeclared=*/true); Destructor->setAccess(AS_public); Destructor->setImplicit(); + Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); ClassDecl->addDecl(Destructor); } } void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) { - TemplateDecl *Template = TemplateD.getAs<TemplateDecl>(); - if (!Template) + 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 return; - TemplateParameterList *Params = Template->getTemplateParameters(); for (TemplateParameterList::iterator Param = Params->begin(), ParamEnd = Params->end(); Param != ParamEnd; ++Param) { @@ -1317,10 +2098,12 @@ void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) { void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) { if (!MethodD) return; - + + AdjustDeclIfTemplate(MethodD); + CXXScopeSpec SS; FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>()); - QualType ClassTy + QualType ClassTy = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext())); SS.setScopeRep( NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr())); @@ -1335,7 +2118,7 @@ void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) { void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) { if (!ParamD) return; - + ParmVarDecl *Param = cast<ParmVarDecl>(ParamD.getAs<Decl>()); // If this parameter has an unparsed default argument, clear it out @@ -1357,10 +2140,12 @@ void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) { void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) { if (!MethodD) return; - + + AdjustDeclIfTemplate(MethodD); + FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>()); CXXScopeSpec SS; - QualType ClassTy + QualType ClassTy = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext())); SS.setScopeRep( NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr())); @@ -1408,26 +2193,26 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, D.setInvalidType(); SC = FunctionDecl::None; } - + DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; if (FTI.TypeQuals != 0) { - if (FTI.TypeQuals & QualType::Const) + if (FTI.TypeQuals & Qualifiers::Const) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) << "const" << SourceRange(D.getIdentifierLoc()); - if (FTI.TypeQuals & QualType::Volatile) + if (FTI.TypeQuals & Qualifiers::Volatile) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) << "volatile" << SourceRange(D.getIdentifierLoc()); - if (FTI.TypeQuals & QualType::Restrict) + if (FTI.TypeQuals & Qualifiers::Restrict) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) << "restrict" << SourceRange(D.getIdentifierLoc()); } - + // 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. - const FunctionProtoType *Proto = R->getAsFunctionProtoType(); + const FunctionProtoType *Proto = R->getAs<FunctionProtoType>(); return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(), Proto->getNumArgs(), Proto->isVariadic(), 0); @@ -1437,7 +2222,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, /// well-formedness, issuing any diagnostics required. Returns true if /// the constructor declarator is invalid. void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { - CXXRecordDecl *ClassDecl + CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(Constructor->getDeclContext()); if (!ClassDecl) return Constructor->setInvalidDecl(); @@ -1448,8 +2233,8 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { // either there are no other parameters or else all other // parameters have default arguments. if (!Constructor->isInvalidDecl() && - ((Constructor->getNumParams() == 1) || - (Constructor->getNumParams() > 1 && + ((Constructor->getNumParams() == 1) || + (Constructor->getNumParams() > 1 && Constructor->getParamDecl(1)->hasDefaultArg()))) { QualType ParamType = Constructor->getParamDecl(0)->getType(); QualType ClassTy = Context.getTagDeclType(ClassDecl); @@ -1460,12 +2245,12 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { Constructor->setInvalidDecl(); } } - + // Notify the class that we've added a constructor. ClassDecl->addedConstructor(Context, Constructor); } -static inline bool +static inline bool FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) { return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && FTI.ArgInfo[0].Param && @@ -1485,7 +2270,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, // (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. - QualType DeclaratorType = QualType::getFromOpaquePtr(D.getDeclaratorIdType()); + QualType DeclaratorType = GetTypeFromParser(D.getDeclaratorIdType()); if (isa<TypedefType>(DeclaratorType)) { Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) << DeclaratorType; @@ -1521,16 +2306,16 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) << SourceRange(D.getIdentifierLoc()); } - + DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; if (FTI.TypeQuals != 0 && !D.isInvalidType()) { - if (FTI.TypeQuals & QualType::Const) + if (FTI.TypeQuals & Qualifiers::Const) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) << "const" << SourceRange(D.getIdentifierLoc()); - if (FTI.TypeQuals & QualType::Volatile) + if (FTI.TypeQuals & Qualifiers::Volatile) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) << "volatile" << SourceRange(D.getIdentifierLoc()); - if (FTI.TypeQuals & QualType::Restrict) + if (FTI.TypeQuals & Qualifiers::Restrict) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) << "restrict" << SourceRange(D.getIdentifierLoc()); D.setInvalidType(); @@ -1545,7 +2330,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, D.setInvalidType(); } - // Make sure the destructor isn't variadic. + // Make sure the destructor isn't variadic. if (FTI.isVariadic) { Diag(D.getIdentifierLoc(), diag::err_destructor_variadic); D.setInvalidType(); @@ -1569,8 +2354,8 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, FunctionDecl::StorageClass& SC) { // C++ [class.conv.fct]p1: // Neither parameter types nor return type can be specified. The - // type of a conversion function (8.3.5) is “function taking no - // parameter returning conversion-type-id.” + // type of a conversion function (8.3.5) is "function taking no + // parameter returning conversion-type-id." if (SC == FunctionDecl::Static) { if (!D.isInvalidType()) Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member) @@ -1594,7 +2379,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, } // Make sure we don't have any parameters. - if (R->getAsFunctionProtoType()->getNumArgs() > 0) { + if (R->getAs<FunctionProtoType>()->getNumArgs() > 0) { Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params); // Delete the parameters. @@ -1602,8 +2387,8 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, D.setInvalidType(); } - // Make sure the conversion function isn't variadic. - if (R->getAsFunctionProtoType()->isVariadic() && !D.isInvalidType()) { + // Make sure the conversion function isn't variadic. + if (R->getAs<FunctionProtoType>()->isVariadic() && !D.isInvalidType()) { Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic); D.setInvalidType(); } @@ -1611,7 +2396,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, // C++ [class.conv.fct]p4: // The conversion-type-id shall not represent a function type nor // an array type. - QualType ConvType = QualType::getFromOpaquePtr(D.getDeclaratorIdType()); + QualType ConvType = GetTypeFromParser(D.getDeclaratorIdType()); if (ConvType->isArrayType()) { Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array); ConvType = Context.getPointerType(ConvType); @@ -1624,13 +2409,13 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, // Rebuild the function type "R" without any parameters (in case any // of the errors above fired) and with the conversion type as the - // return type. - R = Context.getFunctionType(ConvType, 0, 0, false, - R->getAsFunctionProtoType()->getTypeQuals()); + // return type. + R = Context.getFunctionType(ConvType, 0, 0, false, + R->getAs<FunctionProtoType>()->getTypeQuals()); // C++0x explicit conversion operators. if (D.getDeclSpec().isExplicitSpecified() && !getLangOptions().CPlusPlus0x) - Diag(D.getDeclSpec().getExplicitSpecLoc(), + Diag(D.getDeclSpec().getExplicitSpecLoc(), diag::warn_explicit_conversion_functions) << SourceRange(D.getDeclSpec().getExplicitSpecLoc()); } @@ -1642,9 +2427,6 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { assert(Conversion && "Expected to receive a conversion function declaration"); - // Set the lexical context of this conversion function - Conversion->setLexicalDeclContext(CurContext); - CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Conversion->getDeclContext()); // Make sure we aren't redeclaring the conversion function. @@ -1658,9 +2440,9 @@ Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { // or to (possibly cv-qualified) void. // FIXME: Suppress this warning if the conversion function ends up being a // virtual function that overrides a virtual function in a base class. - QualType ClassType + QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); - if (const ReferenceType *ConvTypeRef = ConvType->getAsReferenceType()) + if (const ReferenceType *ConvTypeRef = ConvType->getAs<ReferenceType>()) ConvType = ConvTypeRef->getPointeeType(); if (ConvType->isRecordType()) { ConvType = Context.getCanonicalType(ConvType).getUnqualifiedType(); @@ -1676,20 +2458,26 @@ Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { } if (Conversion->getPreviousDeclaration()) { + const NamedDecl *ExpectedPrevDecl = Conversion->getPreviousDeclaration(); + if (FunctionTemplateDecl *ConversionTemplate + = Conversion->getDescribedFunctionTemplate()) + ExpectedPrevDecl = ConversionTemplate->getPreviousDeclaration(); OverloadedFunctionDecl *Conversions = ClassDecl->getConversionFunctions(); - for (OverloadedFunctionDecl::function_iterator + for (OverloadedFunctionDecl::function_iterator Conv = Conversions->function_begin(), ConvEnd = Conversions->function_end(); Conv != ConvEnd; ++Conv) { - if (*Conv - == cast_or_null<NamedDecl>(Conversion->getPreviousDeclaration())) { + if (*Conv == ExpectedPrevDecl) { *Conv = Conversion; return DeclPtrTy::make(Conversion); } } assert(Conversion->isInvalidDecl() && "Conversion should not get here."); - } else - ClassDecl->addConversionFunction(Context, Conversion); + } else if (FunctionTemplateDecl *ConversionTemplate + = Conversion->getDescribedFunctionTemplate()) + ClassDecl->addConversionFunction(ConversionTemplate); + else if (!Conversion->getPrimaryTemplate()) // ignore specializations + ClassDecl->addConversionFunction(Conversion); return DeclPtrTy::make(Conversion); } @@ -1718,9 +2506,9 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // original-namespace-definition is the name of the namespace. Subsequently // in that declarative region, it is treated as an original-namespace-name. - NamedDecl *PrevDecl = LookupName(DeclRegionScope, II, LookupOrdinaryName, - true); - + NamedDecl *PrevDecl + = LookupSingleName(DeclRegionScope, II, LookupOrdinaryName, true); + 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 @@ -1728,7 +2516,7 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, OrigNS->setNextNamespace(Namespc); Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace()); - // Remove the previous declaration from the scope. + // Remove the previous declaration from the scope. if (DeclRegionScope->isDeclScope(DeclPtrTy::make(OrigNS))) { IdResolver.RemoveDecl(OrigNS); DeclRegionScope->RemoveDecl(DeclPtrTy::make(OrigNS)); @@ -1740,11 +2528,57 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, Diag(PrevDecl->getLocation(), diag::note_previous_definition); Namespc->setInvalidDecl(); // Continue on to push Namespc as current DeclContext and return it. - } + } else if (II->isStr("std") && + CurContext->getLookupContext()->isTranslationUnit()) { + // This is the first "real" definition of the namespace "std", so update + // our cache of the "std" namespace to point at this definition. + if (StdNamespace) { + // We had already defined a dummy namespace "std". Link this new + // namespace definition to the dummy namespace "std". + StdNamespace->setNextNamespace(Namespc); + StdNamespace->setLocation(IdentLoc); + Namespc->setOriginalNamespace(StdNamespace->getOriginalNamespace()); + } + + // Make our StdNamespace cache point at the first real definition of the + // "std" namespace. + StdNamespace = Namespc; + } PushOnScopeChains(Namespc, DeclRegionScope); } else { - // FIXME: Handle anonymous namespaces + // Anonymous namespaces. + + // C++ [namespace.unnamed]p1. An unnamed-namespace-definition + // behaves as if it were replaced by + // namespace unique { /* empty body */ } + // using namespace unique; + // namespace unique { namespace-body } + // where all occurrences of 'unique' in a translation unit are + // replaced by the same identifier and this identifier differs + // from all other identifiers in the entire program. + + // We just create the namespace with an empty name and then add an + // implicit using declaration, just like the standard suggests. + // + // CodeGen enforces the "universally unique" aspect by giving all + // declarations semantically contained within an anonymous + // namespace internal linkage. + + assert(Namespc->isAnonymousNamespace()); + CurContext->addDecl(Namespc); + + UsingDirectiveDecl* UD + = UsingDirectiveDecl::Create(Context, CurContext, + /* 'using' */ LBrace, + /* 'namespace' */ SourceLocation(), + /* qualifier */ SourceRange(), + /* NNS */ NULL, + /* identifier */ SourceLocation(), + Namespc, + /* Ancestor */ CurContext); + UD->setImplicit(); + CurContext->addDecl(UD); } // Although we could have an invalid decl (i.e. the namespace name is a @@ -1781,13 +2615,14 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, UsingDirectiveDecl *UDir = 0; // Lookup namespace name. - LookupResult R = LookupParsedName(S, &SS, NamespcName, - LookupNamespaceName, false); + LookupResult R; + LookupParsedName(R, S, &SS, NamespcName, LookupNamespaceName, false); if (R.isAmbiguous()) { DiagnoseAmbiguousLookup(R, NamespcName, IdentLoc); return DeclPtrTy(); } - if (NamedDecl *NS = R) { + if (!R.empty()) { + NamedDecl *NS = R.getFoundDecl(); assert(isa<NamespaceDecl>(NS) && "expected namespace decl"); // C++ [namespace.udir]p1: // A using-directive specifies that the names in the nominated @@ -1796,8 +2631,8 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, // 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 - // namespace. [Note: in this context, “contains” means “contains - // directly or indirectly”. ] + // namespace. [Note: in this context, "contains" means "contains + // directly or indirectly". ] // Find enclosing context containing both using-directive and // nominated namespace. @@ -1805,9 +2640,9 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, while (CommonAncestor && !CommonAncestor->Encloses(CurContext)) CommonAncestor = CommonAncestor->getParent(); - UDir = UsingDirectiveDecl::Create(Context, + UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, - NamespcLoc, + NamespcLoc, SS.getRange(), (NestedNameSpecifier *)SS.getScopeRep(), IdentLoc, @@ -1837,45 +2672,124 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, - SourceLocation UsingLoc, - const CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *TargetName, - OverloadedOperatorKind Op, - AttributeList *AttrList, - bool IsTypeName) { - assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); + AccessSpecifier AS, + SourceLocation UsingLoc, + const CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *TargetName, + OverloadedOperatorKind Op, + AttributeList *AttrList, + bool IsTypeName) { assert((TargetName || Op) && "Invalid TargetName."); - assert(IdentLoc.isValid() && "Invalid TargetName location."); assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); - UsingDecl *UsingAlias = 0; - DeclarationName Name; if (TargetName) Name = TargetName; else Name = Context.DeclarationNames.getCXXOperatorName(Op); - - // Lookup target name. - LookupResult R = LookupParsedName(S, &SS, Name, LookupOrdinaryName, false); - if (NamedDecl *NS = R) { - if (IsTypeName && !isa<TypeDecl>(NS)) { - Diag(IdentLoc, diag::err_using_typename_non_type); - } - UsingAlias = UsingDecl::Create(Context, CurContext, IdentLoc, SS.getRange(), - NS->getLocation(), UsingLoc, NS, - static_cast<NestedNameSpecifier *>(SS.getScopeRep()), - IsTypeName); - PushOnScopeChains(UsingAlias, S); - } else { - Diag(IdentLoc, diag::err_using_requires_qualname) << SS.getRange(); + NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS, IdentLoc, + Name, AttrList, IsTypeName); + if (UD) { + PushOnScopeChains(UD, S); + UD->setAccess(AS); } + 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."); + // FIXME: We ignore attributes for now. delete AttrList; - return DeclPtrTy::make(UsingAlias); + + if (SS.isEmpty()) { + Diag(IdentLoc, diag::err_using_requires_qualname); + return 0; + } + + NestedNameSpecifier *NNS = + static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + + if (isUnknownSpecialization(SS)) { + return UnresolvedUsingDecl::Create(Context, CurContext, UsingLoc, + SS.getRange(), NNS, + IdentLoc, Name, IsTypeName); + } + + DeclContext *LookupContext = 0; + + 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 + // defined, or shall refer to an enumerator for an enumeration type that is + // 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(); + return 0; + } + + QualType BaseTy = Context.getCanonicalType(QualType(Ty, 0)); + LookupContext = BaseTy->getAs<RecordType>()->getDecl(); + } else { + // C++0x N2914 [namespace.udecl]p8: + // A using-declaration for a class member shall be a member-declaration. + if (NNS->getKind() == NestedNameSpecifier::TypeSpec) { + Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_class_member) + << SS.getRange(); + return 0; + } + + // 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(); + } + + + // Lookup target name. + LookupResult R; + LookupQualifiedName(R, LookupContext, Name, LookupOrdinaryName); + + if (R.empty()) { + Diag(IdentLoc, diag::err_no_member) + << Name << LookupContext << SS.getRange(); + return 0; + } + + // FIXME: handle ambiguity? + NamedDecl *ND = R.getAsSingleDecl(Context); + + if (IsTypeName && !isa<TypeDecl>(ND)) { + Diag(IdentLoc, diag::err_using_typename_non_type); + return 0; + } + + // 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(); + return 0; + } + + return UsingDecl::Create(Context, CurContext, IdentLoc, SS.getRange(), + ND->getLocation(), UsingLoc, ND, NNS, IsTypeName); } /// getNamespaceDecl - Returns the namespace a decl represents. If the decl @@ -1886,26 +2800,29 @@ static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) { return dyn_cast_or_null<NamespaceDecl>(D); } -Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, +Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, const CXXScopeSpec &SS, SourceLocation IdentLoc, IdentifierInfo *Ident) { - + // Lookup the namespace name. - LookupResult R = LookupParsedName(S, &SS, Ident, LookupNamespaceName, false); + LookupResult R; + LookupParsedName(R, S, &SS, Ident, LookupNamespaceName, false); // Check if we have a previous declaration with the same name. - if (NamedDecl *PrevDecl = LookupName(S, Alias, LookupOrdinaryName, true)) { + if (NamedDecl *PrevDecl + = LookupSingleName(S, Alias, LookupOrdinaryName, true)) { if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) { - // We already have an alias with the same name that points to the same + // We already have an alias with the same name that points to the same // namespace, so don't create a new one. - if (!R.isAmbiguous() && AD->getNamespace() == getNamespaceDecl(R)) + if (!R.isAmbiguous() && !R.empty() && + AD->getNamespace() == getNamespaceDecl(R.getFoundDecl())) return DeclPtrTy(); } - + unsigned DiagID = isa<NamespaceDecl>(PrevDecl) ? diag::err_redefinition : diag::err_redefinition_different_kind; Diag(AliasLoc, DiagID) << Alias; @@ -1917,18 +2834,18 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, DiagnoseAmbiguousLookup(R, Ident, IdentLoc); return DeclPtrTy(); } - - if (!R) { + + if (R.empty()) { Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange(); return DeclPtrTy(); } - + NamespaceAliasDecl *AliasDecl = - NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc, - Alias, SS.getRange(), + NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc, + Alias, SS.getRange(), (NestedNameSpecifier *)SS.getScopeRep(), - IdentLoc, R); - + IdentLoc, R.getFoundDecl()); + CurContext->addDecl(AliasDecl); return DeclPtrTy::make(AliasDecl); } @@ -1938,11 +2855,11 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, assert((Constructor->isImplicit() && Constructor->isDefaultConstructor() && !Constructor->isUsed()) && "DefineImplicitDefaultConstructor - call it for implicit default ctor"); - + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Constructor->getDeclContext()); assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); - // Before the implicitly-declared default constructor for a class is + // Before the implicitly-declared default constructor for a class is // implicitly defined, all the implicitly-declared default constructors // for its base class and its non-static data members shall have been // implicitly defined. @@ -1950,16 +2867,16 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), E = ClassDecl->bases_end(); Base != E; ++Base) { CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl()); + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); if (!BaseClassDecl->hasTrivialConstructor()) { - if (CXXConstructorDecl *BaseCtor = + if (CXXConstructorDecl *BaseCtor = BaseClassDecl->getDefaultConstructor(Context)) MarkDeclarationReferenced(CurrentLocation, BaseCtor); else { - Diag(CurrentLocation, diag::err_defining_default_ctor) - << Context.getTagDeclType(ClassDecl) << 1 + Diag(CurrentLocation, diag::err_defining_default_ctor) + << Context.getTagDeclType(ClassDecl) << 0 << Context.getTagDeclType(BaseClassDecl); - Diag(BaseClassDecl->getLocation(), diag::note_previous_class_decl) + Diag(BaseClassDecl->getLocation(), diag::note_previous_class_decl) << Context.getTagDeclType(BaseClassDecl); err = true; } @@ -1970,32 +2887,31 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, QualType FieldType = Context.getCanonicalType((*Field)->getType()); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) FieldType = Array->getElementType(); - if (const RecordType *FieldClassType = FieldType->getAsRecordType()) { + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(FieldClassType->getDecl()); if (!FieldClassDecl->hasTrivialConstructor()) { - if (CXXConstructorDecl *FieldCtor = + if (CXXConstructorDecl *FieldCtor = FieldClassDecl->getDefaultConstructor(Context)) MarkDeclarationReferenced(CurrentLocation, FieldCtor); else { - Diag(CurrentLocation, diag::err_defining_default_ctor) - << Context.getTagDeclType(ClassDecl) << 0 << + Diag(CurrentLocation, diag::err_defining_default_ctor) + << Context.getTagDeclType(ClassDecl) << 1 << Context.getTagDeclType(FieldClassDecl); - Diag(FieldClassDecl->getLocation(), diag::note_previous_class_decl) + Diag((*Field)->getLocation(), diag::note_field_decl); + Diag(FieldClassDecl->getLocation(), diag::note_previous_class_decl) << Context.getTagDeclType(FieldClassDecl); err = true; } } - } - else if (FieldType->isReferenceType()) { - Diag(CurrentLocation, diag::err_unintialized_member) - << Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getNameAsCString(); + } else if (FieldType->isReferenceType()) { + Diag(CurrentLocation, diag::err_unintialized_member) + << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName(); Diag((*Field)->getLocation(), diag::note_declared_at); err = true; - } - else if (FieldType.isConstQualified()) { - Diag(CurrentLocation, diag::err_unintialized_member) - << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getNameAsCString(); + } else if (FieldType.isConstQualified()) { + Diag(CurrentLocation, diag::err_unintialized_member) + << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName(); Diag((*Field)->getLocation(), diag::note_declared_at); err = true; } @@ -2007,47 +2923,47 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, } void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, - CXXDestructorDecl *Destructor) { + CXXDestructorDecl *Destructor) { assert((Destructor->isImplicit() && !Destructor->isUsed()) && "DefineImplicitDestructor - call it for implicit default dtor"); - + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Destructor->getDeclContext()); assert(ClassDecl && "DefineImplicitDestructor - invalid destructor"); // C++ [class.dtor] p5 - // Before the implicitly-declared default destructor for a class is + // Before the implicitly-declared default destructor for a class is // implicitly defined, all the implicitly-declared default destructors // for its base class and its non-static data members shall have been // implicitly defined. for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), E = ClassDecl->bases_end(); Base != E; ++Base) { CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl()); + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); if (!BaseClassDecl->hasTrivialDestructor()) { - if (CXXDestructorDecl *BaseDtor = + if (CXXDestructorDecl *BaseDtor = const_cast<CXXDestructorDecl*>(BaseClassDecl->getDestructor(Context))) MarkDeclarationReferenced(CurrentLocation, BaseDtor); else - assert(false && + assert(false && "DefineImplicitDestructor - missing dtor in a base class"); } } - + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), E = ClassDecl->field_end(); Field != E; ++Field) { QualType FieldType = Context.getCanonicalType((*Field)->getType()); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) FieldType = Array->getElementType(); - if (const RecordType *FieldClassType = FieldType->getAsRecordType()) { + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(FieldClassType->getDecl()); if (!FieldClassDecl->hasTrivialDestructor()) { - if (CXXDestructorDecl *FieldDtor = + if (CXXDestructorDecl *FieldDtor = const_cast<CXXDestructorDecl*>( FieldClassDecl->getDestructor(Context))) MarkDeclarationReferenced(CurrentLocation, FieldDtor); else - assert(false && + assert(false && "DefineImplicitDestructor - missing dtor in class of a data member"); } } @@ -2061,10 +2977,10 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation, MethodDecl->getOverloadedOperator() == OO_Equal && !MethodDecl->isUsed()) && "DefineImplicitOverloadedAssign - call it for implicit assignment op"); - + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(MethodDecl->getDeclContext()); - + // C++[class.copy] p12 // Before the implicitly-declared copy assignment operator for a class is // implicitly defined, all implicitly-declared copy assignment operators @@ -2074,8 +2990,8 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation, for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), E = ClassDecl->bases_end(); Base != E; ++Base) { CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl()); - if (CXXMethodDecl *BaseAssignOpMethod = + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (CXXMethodDecl *BaseAssignOpMethod = getAssignOperatorMethod(MethodDecl->getParamDecl(0), BaseClassDecl)) MarkDeclarationReferenced(CurrentLocation, BaseAssignOpMethod); } @@ -2084,30 +3000,28 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation, QualType FieldType = Context.getCanonicalType((*Field)->getType()); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) FieldType = Array->getElementType(); - if (const RecordType *FieldClassType = FieldType->getAsRecordType()) { + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(FieldClassType->getDecl()); - if (CXXMethodDecl *FieldAssignOpMethod = + if (CXXMethodDecl *FieldAssignOpMethod = getAssignOperatorMethod(MethodDecl->getParamDecl(0), FieldClassDecl)) MarkDeclarationReferenced(CurrentLocation, FieldAssignOpMethod); - } - else if (FieldType->isReferenceType()) { - Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) - << Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getNameAsCString(); - Diag((*Field)->getLocation(), diag::note_declared_at); + } else if (FieldType->isReferenceType()) { + Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) + << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName(); + Diag(Field->getLocation(), diag::note_declared_at); Diag(CurrentLocation, diag::note_first_required_here); err = true; - } - else if (FieldType.isConstQualified()) { - Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) - << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getNameAsCString(); - Diag((*Field)->getLocation(), diag::note_declared_at); + } else if (FieldType.isConstQualified()) { + Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) + << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName(); + Diag(Field->getLocation(), diag::note_declared_at); Diag(CurrentLocation, diag::note_first_required_here); err = true; } } if (!err) - MethodDecl->setUsed(); + MethodDecl->setUsed(); } CXXMethodDecl * @@ -2116,24 +3030,22 @@ Sema::getAssignOperatorMethod(ParmVarDecl *ParmDecl, QualType LHSType = Context.getTypeDeclType(ClassDecl); QualType RHSType(LHSType); // If class's assignment operator argument is const/volatile qualified, - // look for operator = (const/volatile B&). Otherwise, look for + // look for operator = (const/volatile B&). Otherwise, look for // operator = (B&). - if (ParmDecl->getType().isConstQualified()) - RHSType.addConst(); - if (ParmDecl->getType().isVolatileQualified()) - RHSType.addVolatile(); - ExprOwningPtr<Expr> LHS(this, new (Context) DeclRefExpr(ParmDecl, - LHSType, + RHSType = Context.getCVRQualifiedType(RHSType, + ParmDecl->getType().getCVRQualifiers()); + ExprOwningPtr<Expr> LHS(this, new (Context) DeclRefExpr(ParmDecl, + LHSType, SourceLocation())); - ExprOwningPtr<Expr> RHS(this, new (Context) DeclRefExpr(ParmDecl, - RHSType, + ExprOwningPtr<Expr> RHS(this, new (Context) DeclRefExpr(ParmDecl, + RHSType, SourceLocation())); Expr *Args[2] = { &*LHS, &*RHS }; OverloadCandidateSet CandidateSet; - AddMemberOperatorCandidates(clang::OO_Equal, SourceLocation(), Args, 2, + AddMemberOperatorCandidates(clang::OO_Equal, SourceLocation(), Args, 2, CandidateSet); OverloadCandidateSet::iterator Best; - if (BestViableFunction(CandidateSet, + if (BestViableFunction(CandidateSet, ClassDecl->getLocation(), Best) == OR_Success) return cast<CXXMethodDecl>(Best->Function); assert(false && @@ -2144,24 +3056,24 @@ Sema::getAssignOperatorMethod(ParmVarDecl *ParmDecl, void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *CopyConstructor, unsigned TypeQuals) { - assert((CopyConstructor->isImplicit() && + assert((CopyConstructor->isImplicit() && CopyConstructor->isCopyConstructor(Context, TypeQuals) && !CopyConstructor->isUsed()) && "DefineImplicitCopyConstructor - call it for implicit copy ctor"); - + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CopyConstructor->getDeclContext()); assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor"); // C++ [class.copy] p209 - // Before the implicitly-declared copy constructor for a class is + // Before the implicitly-declared copy constructor for a class is // 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 - = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl()); - if (CXXConstructorDecl *BaseCopyCtor = + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (CXXConstructorDecl *BaseCopyCtor = BaseClassDecl->getCopyConstructor(Context, TypeQuals)) MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor); } @@ -2171,10 +3083,10 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, QualType FieldType = Context.getCanonicalType((*Field)->getType()); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) FieldType = Array->getElementType(); - if (const RecordType *FieldClassType = FieldType->getAsRecordType()) { + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(FieldClassType->getDecl()); - if (CXXConstructorDecl *FieldCopyCtor = + if (CXXConstructorDecl *FieldCopyCtor = FieldClassDecl->getCopyConstructor(Context, TypeQuals)) MarkDeclarationReferenced(CurrentLocation, FieldCopyCtor); } @@ -2182,27 +3094,92 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CopyConstructor->setUsed(); } -void Sema::InitializeVarWithConstructor(VarDecl *VD, +Sema::OwningExprResult +Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, + CXXConstructorDecl *Constructor, + MultiExprArg ExprArgs) { + bool Elidable = false; + + // 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. + + // FIXME: Is this enough? + if (Constructor->isCopyConstructor(Context)) { + Expr *E = ((Expr **)ExprArgs.get())[0]; + while (CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(E)) + E = BE->getSubExpr(); + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) + if (ICE->getCastKind() == CastExpr::CK_NoOp) + E = ICE->getSubExpr(); + + if (isa<CallExpr>(E) || isa<CXXTemporaryObjectExpr>(E)) + Elidable = true; + } + + return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, + Elidable, move(ExprArgs)); +} + +/// BuildCXXConstructExpr - Creates a complete call to a constructor, +/// including handling of its default argument expressions. +Sema::OwningExprResult +Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, + CXXConstructorDecl *Constructor, bool Elidable, + MultiExprArg ExprArgs) { + unsigned NumExprs = ExprArgs.size(); + Expr **Exprs = (Expr **)ExprArgs.release(); + + return Owned(CXXConstructExpr::Create(Context, DeclInitType, Constructor, + Elidable, Exprs, NumExprs)); +} + +Sema::OwningExprResult +Sema::BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Constructor, + QualType Ty, + SourceLocation TyBeginLoc, + MultiExprArg Args, + SourceLocation RParenLoc) { + unsigned NumExprs = Args.size(); + Expr **Exprs = (Expr **)Args.release(); + + return Owned(new (Context) CXXTemporaryObjectExpr(Context, Constructor, Ty, + TyBeginLoc, Exprs, + NumExprs, RParenLoc)); +} + + +bool Sema::InitializeVarWithConstructor(VarDecl *VD, CXXConstructorDecl *Constructor, - QualType DeclInitType, - Expr **Exprs, unsigned NumExprs) { - Expr *Temp = CXXConstructExpr::Create(Context, DeclInitType, Constructor, - false, Exprs, NumExprs); + QualType DeclInitType, + MultiExprArg Exprs) { + OwningExprResult TempResult = + BuildCXXConstructExpr(VD->getLocation(), DeclInitType, Constructor, + move(Exprs)); + if (TempResult.isInvalid()) + return true; + + Expr *Temp = TempResult.takeAs<Expr>(); MarkDeclarationReferenced(VD->getLocation(), Constructor); + Temp = MaybeCreateCXXExprWithTemporaries(Temp, /*DestroyTemps=*/true); VD->setInit(Context, Temp); + + return false; } -void Sema::MarkDestructorReferenced(SourceLocation Loc, QualType DeclInitType) -{ +void Sema::FinalizeVarWithDestructor(VarDecl *VD, QualType DeclInitType) { CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>( - DeclInitType->getAsRecordType()->getDecl()); + DeclInitType->getAs<RecordType>()->getDecl()); if (!ClassDecl->hasTrivialDestructor()) - if (CXXDestructorDecl *Destructor = + if (CXXDestructorDecl *Destructor = const_cast<CXXDestructorDecl*>(ClassDecl->getDestructor(Context))) - MarkDeclarationReferenced(Loc, Destructor); + MarkDeclarationReferenced(VD->getLocation(), Destructor); } -/// AddCXXDirectInitializerToDecl - This action is called immediately after +/// AddCXXDirectInitializerToDecl - This action is called immediately after /// ActOnDeclarator, when a C++ direct initializer is present. /// e.g: "int x(1);" void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, @@ -2218,7 +3195,7 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, // the initializer. if (RealDecl == 0) return; - + VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl); if (!VDecl) { Diag(RealDecl->getLocation(), diag::err_illegal_initializer); @@ -2226,9 +3203,7 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, return; } - // FIXME: Need to handle dependent types and expressions here. - - // We will treat direct-initialization as a copy-initialization: + // We will represent direct-initialization similarly to copy-initialization: // int x(1); -as-> int x = 1; // ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c); // @@ -2238,6 +3213,24 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, // exactly form was it (like the CodeGen) can handle both cases without // special case code. + // 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); + + // Store the initialization expressions as a ParenListExpr. + unsigned NumExprs = Exprs.size(); + VDecl->setInit(Context, + new (Context) ParenListExpr(Context, LParenLoc, + (Expr **)Exprs.release(), + NumExprs, RParenLoc)); + return; + } + + // C++ 8.5p11: // The form of initialization (using parentheses or '=') is generally // insignificant, but does matter when the entity being initialized has a @@ -2254,23 +3247,25 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, } if (VDecl->getType()->isRecordType()) { + ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); + CXXConstructorDecl *Constructor = PerformInitializationByConstructor(DeclInitType, - (Expr **)Exprs.get(), NumExprs, + move(Exprs), VDecl->getLocation(), SourceRange(VDecl->getLocation(), RParenLoc), VDecl->getDeclName(), - IK_Direct); + IK_Direct, + ConstructorArgs); if (!Constructor) RealDecl->setInvalidDecl(); else { VDecl->setCXXDirectInitializer(true); - InitializeVarWithConstructor(VDecl, Constructor, DeclInitType, - (Expr**)Exprs.release(), NumExprs); - // FIXME. Must do all that is needed to destroy the object - // on scope exit. For now, just mark the destructor as used. - MarkDestructorReferenced(VDecl->getLocation(), DeclInitType); + if (InitializeVarWithConstructor(VDecl, Constructor, DeclInitType, + move_arg(ConstructorArgs))) + RealDecl->setInvalidDecl(); + FinalizeVarWithDestructor(VDecl, DeclInitType); } return; } @@ -2291,31 +3286,41 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, /*DirectInit=*/true); } -/// PerformInitializationByConstructor - Perform initialization by -/// constructor (C++ [dcl.init]p14), which may occur as part of -/// direct-initialization or copy-initialization. We are initializing -/// an object of type @p ClassType with the given arguments @p -/// Args. @p Loc is the location in the source code where the -/// initializer occurs (e.g., a declaration, member initializer, -/// functional cast, etc.) while @p Range covers the whole -/// initialization. @p InitEntity is the entity being initialized, -/// which may by the name of a declaration or a type. @p Kind is the -/// kind of initialization we're performing, which affects whether -/// explicit constructors will be considered. When successful, returns -/// the constructor that will be used to perform the initialization; -/// when the initialization fails, emits a diagnostic and returns -/// null. +/// \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. CXXConstructorDecl * Sema::PerformInitializationByConstructor(QualType ClassType, - Expr **Args, unsigned NumArgs, + MultiExprArg ArgsPtr, SourceLocation Loc, SourceRange Range, DeclarationName InitEntity, - InitializationKind Kind) { - const RecordType *ClassRec = ClassType->getAsRecordType(); + InitializationKind Kind, + ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs) { + const RecordType *ClassRec = ClassType->getAs<RecordType>(); assert(ClassRec && "Can only initialize a class type here"); - - // C++ [dcl.init]p14: - // + Expr **Args = (Expr **)ArgsPtr.get(); + unsigned NumArgs = ArgsPtr.size(); + + // C++ [dcl.init]p14: // 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 @@ -2330,17 +3335,31 @@ Sema::PerformInitializationByConstructor(QualType ClassType, OverloadCandidateSet CandidateSet; // Add constructors to the overload set. - DeclarationName ConstructorName + DeclarationName ConstructorName = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(ClassType.getUnqualifiedType())); DeclContext::lookup_const_iterator Con, ConEnd; for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName); Con != ConEnd; ++Con) { - CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = 0; + FunctionTemplateDecl *ConstructorTmpl= dyn_cast<FunctionTemplateDecl>(*Con); + if (ConstructorTmpl) + Constructor + = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl()); + else + Constructor = cast<CXXConstructorDecl>(*Con); + if ((Kind == IK_Direct) || - (Kind == IK_Copy && Constructor->isConvertingConstructor()) || - (Kind == IK_Default && Constructor->isDefaultConstructor())) - AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet); + (Kind == IK_Copy && + Constructor->isConvertingConstructor(/*AllowExplicit=*/false)) || + (Kind == IK_Default && Constructor->isDefaultConstructor())) { + if (ConstructorTmpl) + AddTemplateOverloadCandidate(ConstructorTmpl, false, 0, 0, + Args, NumArgs, CandidateSet); + else + AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet); + } } // FIXME: When we decide not to synthesize the implicitly-declared @@ -2349,9 +3368,10 @@ Sema::PerformInitializationByConstructor(QualType ClassType, OverloadCandidateSet::iterator Best; switch (BestViableFunction(CandidateSet, Loc, Best)) { case OR_Success: - // We found a constructor. Return it. - return cast<CXXConstructorDecl>(Best->Function); - + // We found a constructor. Break out so that we can convert the arguments + // appropriately. + break; + case OR_No_Viable_Function: if (InitEntity) Diag(Loc, diag::err_ovl_no_viable_function_in_init) @@ -2361,7 +3381,7 @@ Sema::PerformInitializationByConstructor(QualType ClassType, << ClassType << Range; PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); return 0; - + case OR_Ambiguous: if (InitEntity) Diag(Loc, diag::err_ovl_ambiguous_init) << InitEntity << Range; @@ -2382,8 +3402,85 @@ Sema::PerformInitializationByConstructor(QualType ClassType, PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); return 0; } + + // Convert the arguments, fill in default arguments, etc. + CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function); + if (CompleteConstructorCall(Constructor, move(ArgsPtr), Loc, ConvertedArgs)) + return 0; - 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; } /// CompareReferenceRelationship - Compare the two types T1 and T2 to @@ -2393,8 +3490,8 @@ Sema::PerformInitializationByConstructor(QualType ClassType, /// 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. -Sema::ReferenceCompareResult -Sema::CompareReferenceRelationship(QualType T1, QualType T2, +Sema::ReferenceCompareResult +Sema::CompareReferenceRelationship(QualType T1, QualType T2, bool& DerivedToBase) { assert(!T1->isReferenceType() && "T1 must be the pointee type of the reference type"); @@ -2406,8 +3503,8 @@ Sema::CompareReferenceRelationship(QualType T1, QualType T2, QualType UnqualT2 = T2.getUnqualifiedType(); // C++ [dcl.init.ref]p4: - // Given types “cv1 T1” and “cv2 T2,” “cv1 T1” is - // reference-related to “cv2 T2” if T1 is the same type as T2, or + // Given types "cv1 T1" and "cv2 T2," "cv1 T1" is + // reference-related to "cv2 T2" if T1 is the same type as T2, or // T1 is a base class of T2. if (UnqualT1 == UnqualT2) DerivedToBase = false; @@ -2420,7 +3517,7 @@ Sema::CompareReferenceRelationship(QualType T1, QualType T2, // least). // C++ [dcl.init.ref]p4: - // "cv1 T1” is reference-compatible with “cv2 T2” if T1 is + // "cv1 T1" is reference-compatible with "cv2 T2" if T1 is // 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 @@ -2450,27 +3547,28 @@ Sema::CompareReferenceRelationship(QualType T1, QualType T2, /// When @p AllowExplicit, we also permit explicit user-defined /// conversion functions. /// When @p ForceRValue, we unconditionally treat the initializer as an rvalue. -bool +bool Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, - ImplicitConversionSequence *ICS, + SourceLocation DeclLoc, bool SuppressUserConversions, - bool AllowExplicit, bool ForceRValue) { + bool AllowExplicit, bool ForceRValue, + ImplicitConversionSequence *ICS) { assert(DeclType->isReferenceType() && "Reference init needs a reference"); - QualType T1 = DeclType->getAsReferenceType()->getPointeeType(); + QualType T1 = DeclType->getAs<ReferenceType>()->getPointeeType(); QualType T2 = Init->getType(); // 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. if (Context.getCanonicalType(T2) == Context.OverloadTy) { - FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Init, DeclType, + FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Init, DeclType, ICS != 0); if (Fn) { // Since we're performing this reference-initialization for // real, update the initializer with the resulting function. if (!ICS) { - if (DiagnoseUseOfDecl(Fn, Init->getSourceRange().getBegin())) + if (DiagnoseUseOfDecl(Fn, DeclLoc)) return true; FixOverloadedFunctionReference(Init, Fn); @@ -2485,7 +3583,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, bool DerivedToBase = false; Expr::isLvalueResult InitLvalue = ForceRValue ? Expr::LV_InvalidExpression : Init->isLvalue(Context); - ReferenceCompareResult RefRelationship + ReferenceCompareResult RefRelationship = CompareReferenceRelationship(T1, T2, DerivedToBase); // Most paths end in a failed conversion. @@ -2493,8 +3591,8 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, ICS->ConversionKind = ImplicitConversionSequence::BadConversion; // C++ [dcl.init.ref]p5: - // A reference to type “cv1 T1” is initialized by an expression - // of type “cv2 T2” as follows: + // A reference to type "cv1 T1" is initialized by an expression + // of type "cv2 T2" as follows: // -- If the initializer expression @@ -2505,14 +3603,14 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, // A&& r = b; if (isRValRef && InitLvalue == Expr::LV_Valid) { if (!ICS) - Diag(Init->getSourceRange().getBegin(), diag::err_lvalue_to_rvalue_ref) + Diag(DeclLoc, diag::err_lvalue_to_rvalue_ref) << Init->getSourceRange(); return true; } bool BindsDirectly = false; - // -- is an lvalue (but is not a bit-field), and “cv1 T1” is - // reference-compatible with “cv2 T2,” or + // -- is an lvalue (but is not a bit-field), and "cv1 T1" is + // reference-compatible with "cv2 T2," or // // Note that the bit-field check is skipped if we are just computing // the implicit conversion sequence (C++ [over.best.ics]p2). @@ -2546,40 +3644,54 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, return false; } else { // Perform the conversion. - // FIXME: Binding to a subobject of the lvalue is going to require more - // AST annotation than this. - ImpCastExprToType(Init, T1, /*isLvalue=*/true); + CastExpr::CastKind CK = CastExpr::CK_NoOp; + if (DerivedToBase) + CK = CastExpr::CK_DerivedToBase; + else if(CheckExceptionSpecCompatibility(Init, T1)) + return true; + ImpCastExprToType(Init, T1, CK, /*isLvalue=*/true); } } // -- has a class type (i.e., T2 is a class type) and can be - // implicitly converted to an lvalue of type “cv3 T3,” - // where “cv1 T1” is reference-compatible with “cv3 T3” + // implicitly converted to an lvalue of type "cv3 T3," + // where "cv1 T1" is reference-compatible with "cv3 T3" // 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)), - if (!isRValRef && !SuppressUserConversions && T2->isRecordType()) { - // FIXME: Look for conversions in base classes! - CXXRecordDecl *T2RecordDecl - = dyn_cast<CXXRecordDecl>(T2->getAsRecordType()->getDecl()); + if (!isRValRef && !SuppressUserConversions && T2->isRecordType() && + !RequireCompleteType(SourceLocation(), T2, 0)) { + CXXRecordDecl *T2RecordDecl + = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl()); OverloadCandidateSet CandidateSet; - OverloadedFunctionDecl *Conversions - = T2RecordDecl->getConversionFunctions(); - for (OverloadedFunctionDecl::function_iterator Func + OverloadedFunctionDecl *Conversions + = T2RecordDecl->getVisibleConversionFunctions(); + for (OverloadedFunctionDecl::function_iterator Func = Conversions->function_begin(); Func != Conversions->function_end(); ++Func) { - CXXConversionDecl *Conv = cast<CXXConversionDecl>(*Func); - + FunctionTemplateDecl *ConvTemplate + = dyn_cast<FunctionTemplateDecl>(*Func); + CXXConversionDecl *Conv; + if (ConvTemplate) + Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); + else + Conv = cast<CXXConversionDecl>(*Func); + // If the conversion function doesn't return a reference type, // it can't be considered for this conversion. if (Conv->getConversionType()->isLValueReferenceType() && - (AllowExplicit || !Conv->isExplicit())) - AddConversionCandidate(Conv, Init, DeclType, CandidateSet); + (AllowExplicit || !Conv->isExplicit())) { + if (ConvTemplate) + AddTemplateConversionCandidate(ConvTemplate, Init, DeclType, + CandidateSet); + else + AddConversionCandidate(Conv, Init, DeclType, CandidateSet); + } } OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Init->getLocStart(), Best)) { + switch (BestViableFunction(CandidateSet, DeclLoc, Best)) { case OR_Success: // This is a direct binding. BindsDirectly = true; @@ -2604,17 +3716,33 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, "Expected a direct reference binding!"); return false; } else { - // Perform the conversion. - // FIXME: Binding to a subobject of the lvalue is going to require more - // AST annotation than this. - ImpCastExprToType(Init, T1, /*isLvalue=*/true); + OwningExprResult InitConversion = + BuildCXXCastArgument(DeclLoc, QualType(), + CastExpr::CK_UserDefinedConversion, + cast<CXXMethodDecl>(Best->Function), + Owned(Init)); + Init = InitConversion.takeAs<Expr>(); + + if (CheckExceptionSpecCompatibility(Init, T1)) + return true; + ImpCastExprToType(Init, T1, CastExpr::CK_UserDefinedConversion, + /*isLvalue=*/true); } break; case OR_Ambiguous: - assert(false && "Ambiguous reference binding conversions not implemented."); + if (ICS) { + for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(); + Cand != CandidateSet.end(); ++Cand) + if (Cand->Viable) + ICS->ConversionFunctionSet.push_back(Cand->Function); + break; + } + Diag(DeclLoc, diag::err_ref_init_ambiguous) << DeclType << Init->getType() + << Init->getSourceRange(); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); return true; - + case OR_No_Viable_Function: case OR_Deleted: // There was no suitable conversion, or we found a deleted @@ -2622,7 +3750,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, break; } } - + if (BindsDirectly) { // C++ [dcl.init.ref]p4: // [...] In all cases where the reference-related or @@ -2636,9 +3764,8 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, // complain about errors, because we should not be checking for // ambiguity (or inaccessibility) unless the reference binding // actually happens. - if (DerivedToBase) - return CheckDerivedToBaseConversion(T2, T1, - Init->getSourceRange().getBegin(), + if (DerivedToBase) + return CheckDerivedToBaseConversion(T2, T1, DeclLoc, Init->getSourceRange()); else return false; @@ -2647,25 +3774,24 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, // -- Otherwise, the reference shall be to a non-volatile const // type (i.e., cv1 shall be const), or the reference shall be an // rvalue reference and the initializer expression shall be an rvalue. - if (!isRValRef && T1.getCVRQualifiers() != QualType::Const) { + if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const) { if (!ICS) - Diag(Init->getSourceRange().getBegin(), - diag::err_not_reference_to_const_init) + Diag(DeclLoc, diag::err_not_reference_to_const_init) << T1 << (InitLvalue != Expr::LV_Valid? "temporary" : "value") << T2 << Init->getSourceRange(); return true; } // -- If the initializer expression is an rvalue, with T2 a - // class type, and “cv1 T1” is reference-compatible with - // “cv2 T2,” the reference is bound in one of the + // class type, and "cv1 T1" is reference-compatible with + // "cv2 T2," the reference is bound in one of the // 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. // - // -- A temporary of type “cv1 T2” [sic] is created, and + // -- A temporary of type "cv1 T2" [sic] is created, and // 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 @@ -2693,14 +3819,17 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, ICS->Standard.RRefBinding = isRValRef; ICS->Standard.CopyConstructor = 0; } else { - // FIXME: Binding to a subobject of the rvalue is going to require more - // AST annotation than this. - ImpCastExprToType(Init, T1, /*isLvalue=*/false); + CastExpr::CastKind CK = CastExpr::CK_NoOp; + if (DerivedToBase) + CK = CastExpr::CK_DerivedToBase; + else if(CheckExceptionSpecCompatibility(Init, T1)) + return true; + ImpCastExprToType(Init, T1, CK, /*isLvalue=*/false); } return false; } - // -- Otherwise, a temporary of type “cv1 T1” is created and + // -- Otherwise, a temporary of type "cv1 T1" is created and // 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 @@ -2713,8 +3842,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, // added qualification. But that wasn't the case, so the reference // initialization fails. if (!ICS) - Diag(Init->getSourceRange().getBegin(), - diag::err_reference_init_drops_quals) + Diag(DeclLoc, diag::err_reference_init_drops_quals) << T1 << (InitLvalue != Expr::LV_Valid? "temporary" : "value") << T2 << Init->getSourceRange(); return true; @@ -2728,8 +3856,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, if (SuppressUserConversions && RefRelationship == Ref_Incompatible && (T1->isRecordType() || T2->isRecordType())) { if (!ICS) - Diag(Init->getSourceRange().getBegin(), - diag::err_typecheck_convert_incompatible) + Diag(DeclLoc, diag::err_typecheck_convert_incompatible) << DeclType << Init->getType() << "initializing" << Init->getSourceRange(); return true; } @@ -2737,7 +3864,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, // Actually try to convert the initializer to T1. if (ICS) { // C++ [over.ics.ref]p2: - // + // // 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 @@ -2747,19 +3874,48 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, // the argument expression. Any difference in top-level // cv-qualification is subsumed by the initialization itself // and does not constitute a conversion. - *ICS = TryImplicitConversion(Init, T1, SuppressUserConversions); + *ICS = TryImplicitConversion(Init, T1, SuppressUserConversions, + /*AllowExplicit=*/false, + /*ForceRValue=*/false, + /*InOverloadResolution=*/false); + // Of course, that's still a reference binding. if (ICS->ConversionKind == ImplicitConversionSequence::StandardConversion) { ICS->Standard.ReferenceBinding = true; ICS->Standard.RRefBinding = isRValRef; - } else if(ICS->ConversionKind == + } else if (ICS->ConversionKind == ImplicitConversionSequence::UserDefinedConversion) { ICS->UserDefined.After.ReferenceBinding = true; ICS->UserDefined.After.RRefBinding = isRValRef; } return ICS->ConversionKind == ImplicitConversionSequence::BadConversion; } else { - return PerformImplicitConversion(Init, T1, "initializing"); + ImplicitConversionSequence Conversions; + bool badConversion = PerformImplicitConversion(Init, T1, "initializing", + false, false, + Conversions); + if (badConversion) { + if ((Conversions.ConversionKind == + ImplicitConversionSequence::BadConversion) + && !Conversions.ConversionFunctionSet.empty()) { + Diag(DeclLoc, + diag::err_lvalue_to_rvalue_ambig_ref) << Init->getSourceRange(); + for (int j = Conversions.ConversionFunctionSet.size()-1; + j >= 0; j--) { + FunctionDecl *Func = Conversions.ConversionFunctionSet[j]; + Diag(Func->getLocation(), diag::err_ovl_candidate); + } + } + else { + if (isRValRef) + Diag(DeclLoc, diag::err_lvalue_to_rvalue_ref) + << Init->getSourceRange(); + else + Diag(DeclLoc, diag::err_invalid_initialization) + << DeclType << Init->getType() << Init->getSourceRange(); + } + } + return badConversion; } } @@ -2772,7 +3928,7 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { OverloadedOperatorKind Op = FnDecl->getOverloadedOperator(); - // C++ [over.oper]p5: + // C++ [over.oper]p5: // 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 @@ -2815,13 +3971,13 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { // An operator function cannot have default arguments (8.3.6), // except where explicitly stated below. // - // Only the function-call operator allows default arguments + // Only the function-call operator allows default arguments // (C++ [over.call]p1). if (Op != OO_Call) { for (FunctionDecl::param_iterator Param = FnDecl->param_begin(); Param != FnDecl->param_end(); ++Param) { if ((*Param)->hasUnparsedDefaultArg()) - return Diag((*Param)->getLocation(), + return Diag((*Param)->getLocation(), diag::err_operator_overload_default_arg) << FnDecl->getDeclName(); else if (Expr *DefArg = (*Param)->getDefaultArg()) @@ -2846,7 +4002,7 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { // [...] Operator functions cannot have more or fewer parameters // than the number required for the corresponding operator, as // described in the rest of this subclause. - unsigned NumParams = FnDecl->getNumParams() + unsigned NumParams = FnDecl->getNumParams() + (isa<CXXMethodDecl>(FnDecl)? 1 : 0); if (Op != OO_Call && ((NumParams == 1 && !CanBeUnaryOperator) || @@ -2870,7 +4026,7 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { // Overloaded operators other than operator() cannot be variadic. if (Op != OO_Call && - FnDecl->getType()->getAsFunctionProtoType()->isVariadic()) { + FnDecl->getType()->getAs<FunctionProtoType>()->isVariadic()) { return Diag(FnDecl->getLocation(), diag::err_operator_overload_variadic) << FnDecl->getDeclName(); } @@ -2895,12 +4051,12 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { 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()) + if (const BuiltinType *BT = LastParam->getType()->getAs<BuiltinType>()) ParamIsInt = BT->getKind() == BuiltinType::Int; if (!ParamIsInt) return Diag(LastParam->getLocation(), - diag::err_operator_overload_post_incdec_must_be_int) + diag::err_operator_overload_post_incdec_must_be_int) << LastParam->getType() << (Op == OO_MinusMinus); } @@ -2910,6 +4066,7 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { assert(isa<CXXMethodDecl>(FnDecl) && "Overloaded = not member, but not filtered."); CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl); + Method->setCopyAssignment(true); Method->getParent()->addedAssignmentOperator(Context, Method); } @@ -2938,11 +4095,11 @@ Sema::DeclPtrTy Sema::ActOnStartLinkageSpecification(Scope *S, Diag(LangLoc, diag::err_bad_language); return DeclPtrTy(); } - + // FIXME: Add all the various semantics of linkage specifications - + LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext, - LangLoc, Language, + LangLoc, Language, LBraceLoc.isValid()); CurContext->addDecl(D); PushDeclContext(S, D); @@ -2965,6 +4122,7 @@ Sema::DeclPtrTy Sema::ActOnFinishLinkageSpecification(Scope *S, /// occurs within a C++ catch clause, returning the newly-created /// variable. VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType, + DeclaratorInfo *DInfo, IdentifierInfo *Name, SourceLocation Loc, SourceRange Range) { @@ -2980,7 +4138,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType, // The exception-declaration shall not denote a pointer or reference to an // incomplete type, other than [cv] void*. // N2844 forbids rvalue references. - if(!ExDeclType->isDependentType() && ExDeclType->isRValueReferenceType()) { + if (!ExDeclType->isDependentType() && ExDeclType->isRValueReferenceType()) { Diag(Loc, diag::err_catch_rvalue_ref) << Range; Invalid = true; } @@ -2988,11 +4146,11 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType, QualType BaseType = ExDeclType; int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference unsigned DK = diag::err_catch_incomplete; - if (const PointerType *Ptr = BaseType->getAsPointerType()) { + if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { BaseType = Ptr->getPointeeType(); Mode = 1; DK = diag::err_catch_incomplete_ptr; - } else if(const ReferenceType *Ref = BaseType->getAsReferenceType()) { + } else if (const ReferenceType *Ref = BaseType->getAs<ReferenceType>()) { // For the purpose of error recovery, we treat rvalue refs like lvalue refs. BaseType = Ref->getPointeeType(); Mode = 2; @@ -3002,7 +4160,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType, !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK)) Invalid = true; - if (!Invalid && !ExDeclType->isDependentType() && + if (!Invalid && !ExDeclType->isDependentType() && RequireNonAbstractType(Loc, ExDeclType, diag::err_abstract_type_in_decl, AbstractVariableType)) @@ -3013,9 +4171,8 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType, // FIXME: Need to check for abstract classes. - VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc, - Name, ExDeclType, VarDecl::None, - Range.getBegin()); + VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc, + Name, ExDeclType, DInfo, VarDecl::None); if (Invalid) ExDecl->setInvalidDecl(); @@ -3026,11 +4183,12 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType, /// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch /// handler. Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { - QualType ExDeclType = GetTypeForDeclarator(D, S); + DeclaratorInfo *DInfo = 0; + QualType ExDeclType = GetTypeForDeclarator(D, S, &DInfo); bool Invalid = D.isInvalidType(); IdentifierInfo *II = D.getIdentifier(); - if (NamedDecl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) { + if (NamedDecl *PrevDecl = LookupSingleName(S, II, LookupOrdinaryName)) { // The scope should be freshly made just for us. There is just no way // it contains any previous declaration. assert(!S->isDeclScope(DeclPtrTy::make(PrevDecl))); @@ -3046,14 +4204,14 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { Invalid = true; } - VarDecl *ExDecl = BuildExceptionDeclaration(S, ExDeclType, + VarDecl *ExDecl = BuildExceptionDeclaration(S, ExDeclType, DInfo, D.getIdentifier(), D.getIdentifierLoc(), D.getDeclSpec().getSourceRange()); if (Invalid) ExDecl->setInvalidDecl(); - + // Add the exception declaration into this scope. if (II) PushOnScopeChains(ExDecl, S); @@ -3064,11 +4222,11 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { return DeclPtrTy::make(ExDecl); } -Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, +Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, ExprArg assertexpr, ExprArg assertmessageexpr) { Expr *AssertExpr = (Expr *)assertexpr.get(); - StringLiteral *AssertMessage = + StringLiteral *AssertMessage = cast<StringLiteral>((Expr *)assertmessageexpr.get()); if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) { @@ -3080,32 +4238,305 @@ Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, } if (Value == 0) { - std::string str(AssertMessage->getStrData(), + std::string str(AssertMessage->getStrData(), AssertMessage->getByteLength()); - Diag(AssertLoc, diag::err_static_assert_failed) + Diag(AssertLoc, diag::err_static_assert_failed) << str << AssertExpr->getSourceRange(); } } - + assertexpr.release(); assertmessageexpr.release(); - Decl *Decl = StaticAssertDecl::Create(Context, CurContext, AssertLoc, + Decl *Decl = StaticAssertDecl::Create(Context, CurContext, AssertLoc, AssertExpr, AssertMessage); - + CurContext->addDecl(Decl); return DeclPtrTy::make(Decl); } -bool Sema::ActOnFriendDecl(Scope *S, SourceLocation FriendLoc, DeclPtrTy Dcl) { - if (!(S->getFlags() & Scope::ClassScope)) { - Diag(FriendLoc, diag::err_friend_decl_outside_class); - return true; +/// Handle a friend type declaration. This works in tandem with +/// ActOnTag. +/// +/// Notes on friend class templates: +/// +/// We generally treat friend class declarations as if they were +/// declaring a class. So, for example, the elaborated type specifier +/// in a friend declaration is required to obey the restrictions of a +/// class-head (i.e. no typedefs in the scope chain), template +/// parameters are required to match up with simple template-ids, &c. +/// However, unlike when declaring a template specialization, it's +/// okay to refer to a template specialization without an empty +/// template parameter declaration, e.g. +/// friend class A<T>::B<unsigned>; +/// We permit this as a special case; if there are any template +/// parameters present at all, require proper matching, i.e. +/// template <> template <class T> friend class A<int>::B; +Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, + const DeclSpec &DS, + MultiTemplateParamsArg TempParams) { + SourceLocation Loc = DS.getSourceRange().getBegin(); + + assert(DS.isFriendSpecified()); + assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified); + + // Try to convert the decl specifier to a type. This works for + // friend templates because ActOnTag never produces a ClassTemplateDecl + // for a TUK_Friend. + bool invalid = false; + QualType SourceTy; + QualType T = ConvertDeclSpecToType(DS, Loc, invalid, SourceTy); + if (invalid) return DeclPtrTy(); + + // This is definitely an error in C++98. It's probably meant to + // be forbidden in C++0x, too, but the specification is just + // poorly written. + // + // The problem is with declarations like the following: + // template <T> friend A<T>::foo; + // where deciding whether a class C is a friend or not now hinges + // on whether there exists an instantiation of A that causes + // 'foo' to equal C. There are restrictions on class-heads + // (which we declare (by fiat) elaborated friend declarations to + // be) that makes this tractable. + // + // FIXME: handle "template <> friend class A<T>;", which + // is possibly well-formed? Who even knows? + if (TempParams.size() && !isa<ElaboratedType>(T)) { + Diag(Loc, diag::err_tagless_friend_type_template) + << DS.getSourceRange(); + return DeclPtrTy(); } - - return false; + + // 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. + // 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. + if (const RecordType *RT = T->getAs<RecordType>()) { + RecordDecl *RD = RT->getDecl(); + + std::string InsertionText = std::string(" ") + RD->getKindName(); + + Diag(DS.getTypeSpecTypeLoc(), diag::err_unelaborated_friend_type) + << (unsigned) RD->getTagKind() + << T + << SourceRange(DS.getFriendSpecLoc()) + << CodeModificationHint::CreateInsertion(DS.getTypeSpecTypeLoc(), + InsertionText); + return DeclPtrTy(); + }else { + Diag(DS.getFriendSpecLoc(), diag::err_unexpected_friend) + << DS.getSourceRange(); + return DeclPtrTy(); + } + } + + // Enum types cannot be friends. + if (T->getAs<EnumType>()) { + Diag(DS.getTypeSpecTypeLoc(), diag::err_enum_friend) + << SourceRange(DS.getFriendSpecLoc()); + return DeclPtrTy(); + } + + // 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. + if (!getLangOptions().CPlusPlus0x) + if (const RecordType *RT = T->getAs<RecordType>()) + if (RT->getDecl()->getDeclContext() == CurContext) + Diag(DS.getFriendSpecLoc(), diag::ext_friend_inner_class); + + Decl *D; + if (TempParams.size()) + D = FriendTemplateDecl::Create(Context, CurContext, Loc, + TempParams.size(), + (TemplateParameterList**) TempParams.release(), + T.getTypePtr(), + DS.getFriendSpecLoc()); + else + D = FriendDecl::Create(Context, CurContext, Loc, T.getTypePtr(), + DS.getFriendSpecLoc()); + D->setAccess(AS_public); + CurContext->addDecl(D); + + return DeclPtrTy::make(D); +} + +Sema::DeclPtrTy +Sema::ActOnFriendFunctionDecl(Scope *S, + Declarator &D, + bool IsDefinition, + MultiTemplateParamsArg TemplateParams) { + const DeclSpec &DS = D.getDeclSpec(); + + assert(DS.isFriendSpecified()); + assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified); + + SourceLocation Loc = D.getIdentifierLoc(); + DeclaratorInfo *DInfo = 0; + QualType T = GetTypeForDeclarator(D, S, &DInfo); + + // C++ [class.friend]p1 + // A friend of a class is a function or class.... + // Note that this sees through typedefs, which is intended. + // 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. + 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. + + CXXScopeSpec &ScopeQual = D.getCXXScopeSpec(); + DeclarationName Name = GetNameForDeclarator(D); + assert(Name); + + // 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. + NamedDecl *PrevDecl = 0; + if (!ScopeQual.isInvalid() && ScopeQual.isSet()) { + // FIXME: RequireCompleteDeclContext + DC = computeDeclContext(ScopeQual); + + // FIXME: handle dependent contexts + if (!DC) return DeclPtrTy(); + + LookupResult R; + LookupQualifiedName(R, DC, Name, LookupOrdinaryName, true); + PrevDecl = R.getAsSingleDecl(Context); + + // 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 (!PrevDecl || !PrevDecl->getDeclContext()->Equals(DC)) { + D.setInvalidType(); + 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->Equals(CurContext)) + Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member); + + // 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(); + + LookupResult R; + LookupQualifiedName(R, DC, Name, LookupOrdinaryName, true); + PrevDecl = R.getAsSingleDecl(Context); + + // TODO: decide what we think about using declarations. + if (PrevDecl) + 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 . . . + // 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 (PrevDecl && DC->Equals(CurContext) && !getLangOptions().CPlusPlus0x) + Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member); + } + + if (DC->isFileContext()) { + // This implies that it has to be an operator or function. + if (D.getKind() == Declarator::DK_Constructor || + D.getKind() == Declarator::DK_Destructor || + D.getKind() == Declarator::DK_Conversion) { + Diag(Loc, diag::err_introducing_special_friend) << + (D.getKind() == Declarator::DK_Constructor ? 0 : + D.getKind() == Declarator::DK_Destructor ? 1 : 2); + return DeclPtrTy(); + } + } + + bool Redeclaration = false; + NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo, PrevDecl, + move(TemplateParams), + IsDefinition, + Redeclaration); + if (!ND) return DeclPtrTy(); + + assert(ND->getDeclContext() == DC); + assert(ND->getLexicalDeclContext() == CurContext); + + // 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. + // + // 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(ND, /* Recoverable=*/ false); + if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) + PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false); + } + + FriendDecl *FrD = FriendDecl::Create(Context, CurContext, + D.getIdentifierLoc(), ND, + DS.getFriendSpecLoc()); + FrD->setAccess(AS_public); + CurContext->addDecl(FrD); + + return DeclPtrTy::make(ND); } void Sema::SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc) { + AdjustDeclIfTemplate(dcl); + Decl *Dcl = dcl.getAs<Decl>(); FunctionDecl *Fn = dyn_cast<FunctionDecl>(Dcl); if (!Fn) { @@ -3142,21 +4573,21 @@ void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) { } } -bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, +bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, const CXXMethodDecl *Old) { - QualType NewTy = New->getType()->getAsFunctionType()->getResultType(); - QualType OldTy = Old->getType()->getAsFunctionType()->getResultType(); + QualType NewTy = New->getType()->getAs<FunctionType>()->getResultType(); + QualType OldTy = Old->getType()->getAs<FunctionType>()->getResultType(); QualType CNewTy = Context.getCanonicalType(NewTy); QualType COldTy = Context.getCanonicalType(OldTy); - if (CNewTy == COldTy && + if (CNewTy == COldTy && CNewTy.getCVRQualifiers() == COldTy.getCVRQualifiers()) return false; - + // Check if the return types are covariant QualType NewClassTy, OldClassTy; - + /// Both types must be pointers or references to classes. if (PointerType *NewPT = dyn_cast<PointerType>(NewTy)) { if (PointerType *OldPT = dyn_cast<PointerType>(OldTy)) { @@ -3169,14 +4600,14 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, OldClassTy = OldRT->getPointeeType(); } } - + // The return types aren't either both pointers or references to a class type. if (NewClassTy.isNull()) { - Diag(New->getLocation(), + Diag(New->getLocation(), diag::err_different_return_type_for_overriding_virtual_function) << New->getDeclName() << NewTy << OldTy; Diag(Old->getLocation(), diag::note_overridden_virtual_function); - + return true; } @@ -3189,9 +4620,9 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, Diag(Old->getLocation(), diag::note_overridden_virtual_function); return true; } - + // Check if we the conversion from derived to base is valid. - if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy, + if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy, diag::err_covariant_return_inaccessible_base, diag::err_covariant_return_ambiguous_derived_to_base_conv, // FIXME: Should this point to the return type? @@ -3200,7 +4631,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, return true; } } - + // The qualifiers of the return types must be the same. if (CNewTy.getCVRQualifiers() != COldTy.getCVRQualifiers()) { Diag(New->getLocation(), @@ -3209,7 +4640,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, Diag(Old->getLocation(), diag::note_overridden_virtual_function); return true; }; - + // The new class type must have the same or less qualifiers as the old type. if (NewClassTy.isMoreQualifiedThan(OldClassTy)) { @@ -3219,7 +4650,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, Diag(Old->getLocation(), diag::note_overridden_virtual_function); return true; }; - + return false; } @@ -3229,6 +4660,8 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, /// static data member of class X, names should be looked up in the scope of /// class X. void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) { + AdjustDeclIfTemplate(Dcl); + Decl *D = Dcl.getAs<Decl>(); // If there is no declaration, there was an error parsing it. if (D == 0) @@ -3238,13 +4671,13 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) { // int foo::bar; if (!D->isOutOfLine()) return; - + // 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. - + // Change current context into the context of the initializing declaration. EnterDeclaratorContext(S, D->getDeclContext()); } @@ -3252,6 +4685,8 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) { /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an /// initializer for the declaration 'Dcl'. void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) { + AdjustDeclIfTemplate(Dcl); + Decl *D = Dcl.getAs<Decl>(); // If there is no declaration, there was an error parsing it. if (D == 0) |