From bb1e3bc1e0be2b8f891db46457a8943451bf4d8b Mon Sep 17 00:00:00 2001 From: rdivacky Date: Fri, 1 Jan 2010 10:34:51 +0000 Subject: Updaet clang to 92395. --- lib/Sema/CodeCompleteConsumer.cpp | 17 +- lib/Sema/Lookup.h | 68 +- lib/Sema/Sema.cpp | 13 +- lib/Sema/Sema.h | 175 +++-- lib/Sema/SemaAccess.cpp | 2 + lib/Sema/SemaCXXCast.cpp | 15 +- lib/Sema/SemaCXXScopeSpec.cpp | 50 +- lib/Sema/SemaChecking.cpp | 3 +- lib/Sema/SemaCodeComplete.cpp | 79 ++- lib/Sema/SemaDecl.cpp | 342 +++++---- lib/Sema/SemaDeclAttr.cpp | 19 +- lib/Sema/SemaDeclCXX.cpp | 449 +++++++----- lib/Sema/SemaDeclObjC.cpp | 13 +- lib/Sema/SemaExpr.cpp | 639 +++++++++-------- lib/Sema/SemaExprCXX.cpp | 274 ++++--- lib/Sema/SemaExprObjC.cpp | 2 +- lib/Sema/SemaInit.cpp | 1140 +++++++++++++++++++----------- lib/Sema/SemaInit.h | 181 +++-- lib/Sema/SemaLookup.cpp | 662 +++++++++++++++-- lib/Sema/SemaOverload.cpp | 397 +++++++++-- lib/Sema/SemaStmt.cpp | 31 +- lib/Sema/SemaTemplate.cpp | 93 ++- lib/Sema/SemaTemplateDeduction.cpp | 156 ++-- lib/Sema/SemaTemplateInstantiate.cpp | 5 +- lib/Sema/SemaTemplateInstantiateDecl.cpp | 29 +- lib/Sema/SemaType.cpp | 39 +- lib/Sema/TreeTransform.h | 96 +-- 27 files changed, 3356 insertions(+), 1633 deletions(-) (limited to 'lib/Sema') diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index d8ed894..b9b85df 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -37,6 +37,7 @@ CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text) case CK_Text: case CK_Placeholder: case CK_Informative: + case CK_ResultType: case CK_CurrentParameter: { char *New = new char [Text.size() + 1]; std::memcpy(New, Text.data(), Text.size()); @@ -112,6 +113,11 @@ CodeCompletionString::Chunk::CreateInformative(StringRef Informative) { } CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreateResultType(StringRef ResultType) { + return Chunk(CK_ResultType, ResultType); +} + +CodeCompletionString::Chunk CodeCompletionString::Chunk::CreateCurrentParameter( StringRef CurrentParameter) { return Chunk(CK_CurrentParameter, CurrentParameter); @@ -123,6 +129,7 @@ CodeCompletionString::Chunk CodeCompletionString::Chunk::Clone() const { case CK_Text: case CK_Placeholder: case CK_Informative: + case CK_ResultType: case CK_CurrentParameter: case CK_LeftParen: case CK_RightParen: @@ -156,6 +163,7 @@ CodeCompletionString::Chunk::Destroy() { case CK_Text: case CK_Placeholder: case CK_Informative: + case CK_ResultType: case CK_CurrentParameter: delete [] Text; break; @@ -186,7 +194,12 @@ std::string CodeCompletionString::getAsString() const { switch (C->Kind) { case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; case CK_Placeholder: OS << "<#" << C->Text << "#>"; break; - case CK_Informative: OS << "[#" << C->Text << "#]"; break; + + case CK_Informative: + case CK_ResultType: + OS << "[#" << C->Text << "#]"; + break; + case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break; default: OS << C->Text; break; } @@ -236,6 +249,7 @@ void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const { case CK_Text: case CK_Placeholder: case CK_Informative: + case CK_ResultType: case CK_CurrentParameter: { const char *Text = C->Text; unsigned StrLen = strlen(Text); @@ -286,6 +300,7 @@ CodeCompletionString *CodeCompletionString::Deserialize(const char *&Str, case CK_Text: case CK_Placeholder: case CK_Informative: + case CK_ResultType: case CK_CurrentParameter: { unsigned StrLen; if (ReadUnsigned(Str, StrEnd, StrLen) || (Str + StrLen > StrEnd)) diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h index 78f79ea..c5eecda 100644 --- a/lib/Sema/Lookup.h +++ b/lib/Sema/Lookup.h @@ -121,6 +121,8 @@ public: typedef llvm::SmallVector DeclsTy; typedef DeclsTy::const_iterator iterator; + typedef bool (*ResultFilter)(NamedDecl*, unsigned IDNS); + LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc, Sema::LookupNameKind LookupKind, Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) @@ -130,11 +132,14 @@ public: Name(Name), NameLoc(NameLoc), LookupKind(LookupKind), + IsAcceptableFn(0), IDNS(0), Redecl(Redecl != Sema::NotForRedeclaration), HideTags(true), Diagnose(Redecl == Sema::NotForRedeclaration) - {} + { + configure(); + } /// Creates a temporary lookup result, initializing its core data /// using the information from another result. Diagnostics are always @@ -146,6 +151,7 @@ public: Name(Other.Name), NameLoc(Other.NameLoc), LookupKind(Other.LookupKind), + IsAcceptableFn(Other.IsAcceptableFn), IDNS(Other.IDNS), Redecl(Other.Redecl), HideTags(Other.HideTags), @@ -162,6 +168,11 @@ public: return Name; } + /// \brief Sets the name to look up. + void setLookupName(DeclarationName Name) { + this->Name = Name; + } + /// Gets the kind of lookup to perform. Sema::LookupNameKind getLookupKind() const { return LookupKind; @@ -178,17 +189,6 @@ public: HideTags = Hide; } - /// The identifier namespace of this lookup. This information is - /// private to the lookup routines. - unsigned getIdentifierNamespace() const { - assert(IDNS); - return IDNS; - } - - void setIdentifierNamespace(unsigned NS) { - IDNS = NS; - } - bool isAmbiguous() const { return getResultKind() == Ambiguous; } @@ -231,7 +231,19 @@ public: return Paths; } - /// \brief Add a declaration to these results. + /// \brief Tests whether the given declaration is acceptable. + bool isAcceptableDecl(NamedDecl *D) const { + assert(IsAcceptableFn); + return IsAcceptableFn(D, IDNS); + } + + /// \brief Returns the identifier namespace mask for this lookup. + unsigned getIdentifierNamespace() const { + return IDNS; + } + + /// \brief Add a declaration to these results. Does not test the + /// acceptance criteria. void addDecl(NamedDecl *D) { Decls.push_back(D); ResultKind = Found; @@ -334,6 +346,7 @@ public: void clear(Sema::LookupNameKind Kind) { clear(); LookupKind = Kind; + configure(); } void print(llvm::raw_ostream &); @@ -362,6 +375,10 @@ public: return NameLoc; } + /// \brief Get the Sema object that this lookup result is searching + /// with. + Sema &getSema() const { return SemaRef; } + /// A class for iterating through a result set and possibly /// filtering out results. The results returned are possibly /// sugared. @@ -438,6 +455,7 @@ private: } void addDeclsFromBasePaths(const CXXBasePaths &P); + void configure(); // Sanity checks. void sanity() const { @@ -476,7 +494,9 @@ private: SourceLocation NameLoc; SourceRange NameContextRange; Sema::LookupNameKind LookupKind; - unsigned IDNS; // ill-defined until set by lookup + ResultFilter IsAcceptableFn; // set by configure() + unsigned IDNS; // set by configure() + bool Redecl; /// \brief True if tag declarations should be hidden if non-tags @@ -486,6 +506,26 @@ private: bool Diagnose; }; + /// \brief Consumes visible declarations found when searching for + /// all visible names within a given scope or context. + /// + /// This abstract class is meant to be subclassed by clients of \c + /// Sema::LookupVisibleDecls(), each of which should override the \c + /// FoundDecl() function to process declarations as they are found. + class VisibleDeclConsumer { + public: + /// \brief Destroys the visible declaration consumer. + virtual ~VisibleDeclConsumer(); + + /// \brief Invoked each time \p Sema::LookupVisibleDecls() finds a + /// declaration visible from the current scope or context. + /// + /// \param ND the declaration found. + /// + /// \param Hiding a declaration that hides the declaration \p ND, + /// or NULL if no such declaration exists. + virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding) = 0; + }; } #endif diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index ef61474..40ad90a 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -350,7 +350,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, : LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), - PreDeclaratorDC(0), CurBlock(0), PackContext(0), ParsingDeclDepth(0), + CurBlock(0), PackContext(0), ParsingDeclDepth(0), IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0), GlobalNewDeleteDeclared(false), CompleteTranslationUnit(CompleteTranslationUnit), @@ -389,12 +389,6 @@ static bool getIntProperties(ASTContext &C, const Type *T, return true; } - if (const FixedWidthIntType *FWIT = dyn_cast(T)) { - BitWidth = FWIT->getWidth(); - Signed = FWIT->isSigned(); - return true; - } - return false; } @@ -655,8 +649,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T) { } // If the target is integral, always warn. - if ((TargetBT && TargetBT->isInteger()) || - isa(Target)) + if ((TargetBT && TargetBT->isInteger())) // TODO: don't warn for integer values? return DiagnoseImpCast(S, E, T, diag::warn_impcast_float_integer); @@ -815,7 +808,7 @@ void Sema::ActOnEndOfTranslationUnit() { //===----------------------------------------------------------------------===// DeclContext *Sema::getFunctionLevelDeclContext() { - DeclContext *DC = PreDeclaratorDC ? PreDeclaratorDC : CurContext; + DeclContext *DC = CurContext; while (isa(DC)) DC = DC->getParent(); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index ada8aa1..4cecee4 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -24,6 +24,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/FullExpr.h" #include "clang/Parse/Action.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallVector.h" @@ -57,6 +58,7 @@ namespace clang { class DesignatedInitExpr; class CallExpr; class DeclRefExpr; + class UnresolvedLookupExpr; class VarDecl; class ParmVarDecl; class TypedefDecl; @@ -98,7 +100,8 @@ namespace clang { class InitializedEntity; class InitializationKind; class InitializationSequence; - + class VisibleDeclConsumer; + /// BlockSemaInfo - When a block is being parsed, this contains information /// about the block. It is pointed to from Sema::CurBlock. struct BlockSemaInfo { @@ -190,10 +193,6 @@ public: /// CurContext - This is the current declaration context of parsing. DeclContext *CurContext; - /// PreDeclaratorDC - Keeps the declaration context before switching to the - /// context of a declarator's nested-name-specifier. - DeclContext *PreDeclaratorDC; - /// CurBlock - If inside of a block definition, this contains a pointer to /// the active block object that represents it. BlockSemaInfo *CurBlock; @@ -611,10 +610,6 @@ public: const LookupResult &Previous, Scope *S); void DiagnoseFunctionSpecifiers(Declarator& D); - bool CheckRedeclaration(DeclContext *DC, - DeclarationName Name, - SourceLocation NameLoc, - unsigned Diagnostic); NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, bool &Redeclaration); @@ -763,6 +758,12 @@ public: /// struct, or union). virtual void ActOnTagStartDefinition(Scope *S, DeclPtrTy TagDecl); + /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a + /// C++ record definition's base-specifiers clause and are starting its + /// member declarations. + virtual void ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagDecl, + SourceLocation LBraceLoc); + /// ActOnTagFinishDefinition - Invoked once we have finished parsing /// the definition of a tag (enumeration, class, struct, or union). virtual void ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagDecl, @@ -841,6 +842,18 @@ public: void MergeVarDecl(VarDecl *New, LookupResult &OldDecls); bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old); + // AssignmentAction - This is used by all the assignment diagnostic functions + // to represent what is actually causing the operation + enum AssignmentAction { + AA_Assigning, + AA_Passing, + AA_Returning, + AA_Converting, + AA_Initializing, + AA_Sending, + AA_Casting + }; + /// C++ Overloading. enum OverloadKind { /// This is a legitimate overload: the existing declarations are @@ -917,9 +930,13 @@ public: TryCopyInitialization(Expr* From, QualType ToType, bool SuppressUserConversions, bool ForceRValue, bool InOverloadResolution); + bool PerformCopyInitialization(Expr *&From, QualType ToType, - const char *Flavor, bool Elidable = false); + AssignmentAction Action, bool Elidable = false); + OwningExprResult PerformCopyInitialization(const InitializedEntity &Entity, + SourceLocation EqualLoc, + OwningExprResult Init); ImplicitConversionSequence TryObjectArgumentInitialization(QualType FromType, CXXMethodDecl *Method, CXXRecordDecl *ActingContext); @@ -1020,27 +1037,23 @@ public: FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, bool Complain); + FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From); + Expr *FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn); OwningExprResult FixOverloadedFunctionReference(OwningExprResult, FunctionDecl *Fn); - void AddOverloadedCallCandidates(llvm::SmallVectorImpl& Callees, - DeclarationName &UnqualifiedName, - bool ArgumentDependentLookup, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet, bool PartialOverloading = false); - FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, - llvm::SmallVectorImpl &Fns, - DeclarationName UnqualifiedName, - const TemplateArgumentListInfo *ExplicitTemplateArgs, - SourceLocation LParenLoc, - Expr **Args, unsigned NumArgs, - SourceLocation *CommaLocs, - SourceLocation RParenLoc, - bool ArgumentDependentLookup); + OwningExprResult BuildOverloadedCallExpr(Expr *Fn, + UnresolvedLookupExpr *ULE, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc); OwningExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned Opc, @@ -1133,7 +1146,7 @@ public: // members. LookupOperatorName, /// Look up of a name that precedes the '::' scope resolution - /// operator in C++. This lookup completely ignores operator, + /// operator in C++. This lookup completely ignores operator, object, /// function, and enumerator names (C++ [basic.lookup.qual]p1). LookupNestedNameSpecifierName, /// Look up a namespace name within a C++ using directive or @@ -1164,36 +1177,6 @@ private: bool CppLookupName(LookupResult &R, Scope *S); public: - /// Determines whether D is a suitable lookup result according to the - /// lookup criteria. - static bool isAcceptableLookupResult(NamedDecl *D, LookupNameKind NameKind, - unsigned IDNS) { - switch (NameKind) { - case Sema::LookupOrdinaryName: - case Sema::LookupTagName: - case Sema::LookupMemberName: - case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping - case Sema::LookupUsingDeclName: - case Sema::LookupObjCProtocolName: - case Sema::LookupObjCImplementationName: - return D->isInIdentifierNamespace(IDNS); - - case Sema::LookupOperatorName: - return D->isInIdentifierNamespace(IDNS) && - !D->getDeclContext()->isRecord(); - - case Sema::LookupNestedNameSpecifierName: - return isa(D) || D->isInIdentifierNamespace(Decl::IDNS_Tag); - - case Sema::LookupNamespaceName: - return isa(D) || isa(D); - } - - assert(false && - "isAcceptableLookupResult always returns before this point"); - return false; - } - /// \brief Look up a name, looking for a single declaration. Return /// null if the results were absent, ambiguous, or overloaded. /// @@ -1215,11 +1198,20 @@ public: void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, QualType T1, QualType T2, FunctionSet &Functions); - + void ArgumentDependentLookup(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, FunctionSet &Functions); + void LookupVisibleDecls(Scope *S, LookupNameKind Kind, + VisibleDeclConsumer &Consumer); + void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, + VisibleDeclConsumer &Consumer); + + bool CorrectTypo(LookupResult &R, Scope *S, const CXXScopeSpec *SS, + DeclContext *MemberContext = 0, + bool EnteringContext = false); + void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses); @@ -1455,7 +1447,8 @@ public: virtual void PopExpressionEvaluationContext(); void MarkDeclarationReferenced(SourceLocation Loc, Decl *D); - + bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD); + // Primary Expressions. virtual SourceRange getExprRange(ExprTy *E) const; @@ -1465,6 +1458,8 @@ public: bool HasTrailingLParen, bool IsAddressOfOperand); + bool DiagnoseEmptyLookup(Scope *S, const CXXScopeSpec &SS, LookupResult &R); + OwningExprResult LookupInObjCMethod(LookupResult &R, Scope *S, IdentifierInfo *II); @@ -1485,6 +1480,9 @@ public: FieldDecl *Field, Expr *BaseObjectExpr = 0, SourceLocation OpLoc = SourceLocation()); + OwningExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs); OwningExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, @@ -1611,16 +1609,6 @@ public: Expr **Args, unsigned NumArgs, SourceLocation RParenLoc); - void DeconstructCallFunction(Expr *FnExpr, - llvm::SmallVectorImpl& Fns, - DeclarationName &Name, - NestedNameSpecifier *&Qualifier, - SourceRange &QualifierRange, - bool &ArgumentDependentLookup, - bool &Overloaded, - bool &HasExplicitTemplateArgs, - TemplateArgumentListInfo &ExplicitTemplateArgs); - /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. /// This provides the location of the left/right parens and a list of comma /// locations. @@ -1812,7 +1800,8 @@ public: OwningExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, - MultiExprArg Exprs); + MultiExprArg Exprs, + bool RequiresZeroInit = false); // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if // the constructor can be elidable? @@ -1820,7 +1809,8 @@ public: QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, - MultiExprArg Exprs); + MultiExprArg Exprs, + bool RequiresZeroInit = false); OwningExprResult BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Cons, QualType writtenTy, @@ -1972,7 +1962,8 @@ public: bool AllowMissing, FunctionDecl *&Operator); void DeclareGlobalNewDelete(); void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return, - QualType Argument); + QualType Argument, + bool addMallocAttr = false); bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, DeclarationName Name, FunctionDecl* &Operator); @@ -2003,9 +1994,10 @@ public: /// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is /// non-empty, will create a new CXXExprWithTemporaries expression. /// Otherwise, just returs the passed in expression. - Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr, - bool ShouldDestroyTemporaries); - + Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr); + OwningExprResult MaybeCreateCXXExprWithTemporaries(OwningExprResult SubExpr); + FullExpr CreateFullExpr(Expr *SubExpr); + virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr); bool RequireCompleteDeclContext(const CXXScopeSpec &SS); @@ -2216,11 +2208,15 @@ public: SourceLocation RBrac); virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template); + virtual void ActOnStartDelayedMemberDeclarations(Scope *S, + DeclPtrTy Record); virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy Method); virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param); virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy Method); + virtual void ActOnFinishDelayedMemberDeclarations(Scope *S, + DeclPtrTy Record); virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc, ExprArg AssertExpr, @@ -2681,7 +2677,10 @@ public: TDK_TooFewArguments, /// \brief The explicitly-specified template arguments were not valid /// template arguments for the given template. - TDK_InvalidExplicitArguments + TDK_InvalidExplicitArguments, + /// \brief The arguments included an overloaded function name that could + /// not be resolved to a suitable function. + TDK_FailedOverloadResolution }; /// \brief Provides information about an attempted template argument @@ -2795,6 +2794,12 @@ public: CXXConversionDecl *&Specialization, TemplateDeductionInfo &Info); + TemplateDeductionResult + DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + const TemplateArgumentListInfo *ExplicitTemplateArgs, + FunctionDecl *&Specialization, + TemplateDeductionInfo &Info); + FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, TemplatePartialOrderingContext TPOC); @@ -3555,14 +3560,14 @@ public: /// represent it in the AST. Incompatible }; - + /// DiagnoseAssignmentResult - Emit a diagnostic, if required, for the /// assignment conversion type specified by ConvTy. This returns true if the /// conversion was invalid or false if the conversion was accepted. bool DiagnoseAssignmentResult(AssignConvertType ConvTy, SourceLocation Loc, QualType DstType, QualType SrcType, - Expr *SrcExpr, const char *Flavor); + Expr *SrcExpr, AssignmentAction Action); /// CheckAssignmentConstraints - Perform type checking for assignment, /// argument passing, variable initialization, and function return values. @@ -3597,25 +3602,24 @@ public: bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType); bool PerformImplicitConversion(Expr *&From, QualType ToType, - const char *Flavor, + AssignmentAction Action, bool AllowExplicit = false, bool Elidable = false); bool PerformImplicitConversion(Expr *&From, QualType ToType, - const char *Flavor, + AssignmentAction Action, bool AllowExplicit, bool Elidable, ImplicitConversionSequence& ICS); bool PerformImplicitConversion(Expr *&From, QualType ToType, const ImplicitConversionSequence& ICS, - const char *Flavor, + AssignmentAction Action, bool IgnoreBaseAccess = false); bool PerformImplicitConversion(Expr *&From, QualType ToType, const StandardConversionSequence& SCS, - const char *Flavor, bool IgnoreBaseAccess); + AssignmentAction Action, bool IgnoreBaseAccess); bool BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind, - const ImplicitConversionSequence& ICS, - const char *Flavor); + const ImplicitConversionSequence& ICS); /// the following "Check" methods will return a valid/converted QualType /// or a null QualType (indicating an error diagnostic was issued). @@ -3675,15 +3679,10 @@ public: SourceLocation CmpLoc); /// type checking declaration initializers (C99 6.7.8) - - bool CheckInitializerTypes(Expr *&simpleInit_or_initList, QualType &declType, - SourceLocation InitLoc,DeclarationName InitEntity, - bool DirectInit); - bool CheckInitList(InitListExpr *&InitList, QualType &DeclType); + bool CheckInitList(const InitializedEntity &Entity, + InitListExpr *&InitList, QualType &DeclType); bool CheckForConstantInitializer(Expr *e, QualType t); - bool CheckValueInitialization(QualType Type, SourceLocation Loc); - // type checking C++ declaration initializers (C++ [dcl.init]). /// ReferenceCompareResult - Expresses the result of comparing two diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index 21f83a5..b7cc37b 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -37,6 +37,8 @@ bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, << MemberDecl << LexicalAS; Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration) << PrevMemberDecl << PrevMemberDecl->getAccess(); + + MemberDecl->setAccess(LexicalAS); return true; } diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 814af90..800c544 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -899,7 +899,7 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, // The conversion is possible, so commit to it. Kind = CastExpr::CK_NoOp; msg = 0; - return Self.PerformImplicitConversion(SrcExpr, DestType, ICS, "casting", + return Self.PerformImplicitConversion(SrcExpr, DestType, ICS, Sema::AA_Casting, /*IgnoreBaseAccess*/CStyle) ? TC_Failed : TC_Success; } @@ -959,8 +959,9 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, // as must be the final pointee type. while (SrcType != DestType && Self.UnwrapSimilarPointerTypes(SrcType, DestType)) { - SrcType = SrcType.getUnqualifiedType(); - DestType = DestType.getUnqualifiedType(); + Qualifiers Quals; + SrcType = Self.Context.getUnqualifiedArrayType(SrcType, Quals); + DestType = Self.Context.getUnqualifiedArrayType(DestType, Quals); } // Since we're dealing in canonical types, the remainder must be the same. @@ -975,8 +976,6 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, const SourceRange &OpRange, unsigned &msg, CastExpr::CastKind &Kind) { - QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType(); - DestType = Self.Context.getCanonicalType(DestType); QualType SrcType = SrcExpr->getType(); if (const ReferenceType *DestTypeTmp = DestType->getAs()) { @@ -1053,8 +1052,11 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, return TC_NotApplicable; // If both types have the same size, we can successfully cast. - if (Self.Context.getTypeSize(SrcType) == Self.Context.getTypeSize(DestType)) + if (Self.Context.getTypeSize(SrcType) + == Self.Context.getTypeSize(DestType)) { + Kind = CastExpr::CK_BitCast; return TC_Success; + } if (destIsScalar) msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size; @@ -1083,6 +1085,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, // to the same type. However, the behavior of compilers is pretty consistent // on this point: allow same-type conversion if the involved types are // pointers, disallow otherwise. + Kind = CastExpr::CK_NoOp; return TC_Success; } diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 039691f..82d58ea 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -329,7 +329,7 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) { /// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in /// that it contains an extra parameter \p ScopeLookupResult, which provides /// the result of name lookup within the scope of the nested-name-specifier -/// that was computed at template definitino time. +/// that was computed at template definition time. /// /// If ErrorRecoveryLookup is true, then this call is used to improve error /// recovery. This means that it should not emit diagnostics, it should @@ -428,6 +428,28 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, } // FIXME: Deal with ambiguities cleanly. + + if (Found.empty() && !ErrorRecoveryLookup) { + // We haven't found anything, and we're not recovering from a + // different kind of error, so look for typos. + DeclarationName Name = Found.getLookupName(); + if (CorrectTypo(Found, S, &SS, LookupCtx, EnteringContext) && + Found.isSingleResult() && + isAcceptableNestedNameSpecifier(Found.getAsSingle())) { + if (LookupCtx) + Diag(Found.getNameLoc(), diag::err_no_member_suggest) + << Name << LookupCtx << Found.getLookupName() << SS.getRange() + << CodeModificationHint::CreateReplacement(Found.getNameLoc(), + Found.getLookupName().getAsString()); + else + Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest) + << Name << Found.getLookupName() + << CodeModificationHint::CreateReplacement(Found.getNameLoc(), + Found.getLookupName().getAsString()); + } else + Found.clear(); + } + NamedDecl *SD = Found.getAsSingle(); if (isAcceptableNestedNameSpecifier(SD)) { if (!ObjectType.isNull() && !ObjectTypeSearchedInScope) { @@ -605,15 +627,18 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { /// The 'SS' should be a non-empty valid CXXScopeSpec. bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); - if (DeclContext *DC = computeDeclContext(SS, true)) { - // Before we enter a declarator's context, we need to make sure that - // it is a complete declaration context. - if (!DC->isDependentContext() && RequireCompleteDeclContext(SS)) - return true; - - EnterDeclaratorContext(S, DC); - } - + + if (SS.isInvalid()) return true; + + DeclContext *DC = computeDeclContext(SS, true); + if (!DC) return true; + + // Before we enter a declarator's context, we need to make sure that + // it is a complete declaration context. + if (!DC->isDependentContext() && RequireCompleteDeclContext(SS)) + return true; + + EnterDeclaratorContext(S, DC); return false; } @@ -626,6 +651,7 @@ void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); if (SS.isInvalid()) return; - if (computeDeclContext(SS, true)) - ExitDeclaratorContext(S); + assert(!SS.isInvalid() && computeDeclContext(SS, true) && + "exiting declarator scope we never really entered"); + ExitDeclaratorContext(S); } diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 28de500..f10fa07 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -747,6 +747,7 @@ bool Sema::SemaBuiltinEHReturnDataRegNo(CallExpr *TheCall) { /// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr, /// int type). This simply type checks that type is one of the defined /// constants (0-3). +// For compatability check 0-3, llvm only handles 0 and 2. bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) { Expr *Arg = TheCall->getArg(1); if (Arg->isTypeDependent()) @@ -800,7 +801,7 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, switch (E->getStmtClass()) { case Stmt::ConditionalOperatorClass: { const ConditionalOperator *C = cast(E); - return SemaCheckStringLiteral(C->getLHS(), TheCall, + return SemaCheckStringLiteral(C->getTrueExpr(), TheCall, HasVAListArg, format_idx, firstDataArg) && SemaCheckStringLiteral(C->getRHS(), TheCall, HasVAListArg, format_idx, firstDataArg); diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 4ce9330..ef82a94 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -829,6 +829,39 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, unsigned Rank, } } +/// \brief If the given declaration has an associated type, add it as a result +/// type chunk. +static void AddResultTypeChunk(ASTContext &Context, + NamedDecl *ND, + CodeCompletionString *Result) { + if (!ND) + return; + + // Determine the type of the declaration (if it has a type). + QualType T; + if (FunctionDecl *Function = dyn_cast(ND)) + T = Function->getResultType(); + else if (ObjCMethodDecl *Method = dyn_cast(ND)) + T = Method->getResultType(); + else if (FunctionTemplateDecl *FunTmpl = dyn_cast(ND)) + T = FunTmpl->getTemplatedDecl()->getResultType(); + else if (EnumConstantDecl *Enumerator = dyn_cast(ND)) + T = Context.getTypeDeclType(cast(Enumerator->getDeclContext())); + else if (isa(ND)) { + /* Do nothing: ignore unresolved using declarations*/ + } else if (ValueDecl *Value = dyn_cast(ND)) + T = Value->getType(); + else if (ObjCPropertyDecl *Property = dyn_cast(ND)) + T = Property->getType(); + + if (T.isNull() || Context.hasSameType(T, Context.DependentTy)) + return; + + std::string TypeStr; + T.getAsStringInternal(TypeStr, Context.PrintingPolicy); + Result->AddResultTypeChunk(TypeStr); +} + /// \brief Add function parameter chunks to the given code completion string. static void AddFunctionParameterChunks(ASTContext &Context, FunctionDecl *Function, @@ -1042,6 +1075,8 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { return Result; } + AddResultTypeChunk(S.Context, ND, Result); + if (FunctionDecl *Function = dyn_cast(ND)) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, S.Context); @@ -1170,6 +1205,13 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { Result->AddPlaceholderChunk(Arg); } + if (Method->isVariadic()) { + if (AllParametersAreInformative) + Result->AddInformativeChunk(", ..."); + else + Result->AddPlaceholderChunk(", ..."); + } + return Result; } @@ -1189,6 +1231,7 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( CodeCompletionString *Result = new CodeCompletionString; FunctionDecl *FDecl = getFunction(); + AddResultTypeChunk(S.Context, FDecl, Result); const FunctionProtoType *Proto = dyn_cast(getFunctionType()); if (!FDecl && !Proto) { @@ -1706,33 +1749,24 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, CodeCompleteOrdinaryName(S); return; } - - llvm::SmallVector Fns; - DeclarationName UnqualifiedName; - NestedNameSpecifier *Qualifier; - SourceRange QualifierRange; - bool ArgumentDependentLookup; - bool Overloaded; - bool HasExplicitTemplateArgs; - TemplateArgumentListInfo ExplicitTemplateArgs; - - DeconstructCallFunction(Fn, Fns, UnqualifiedName, Qualifier, QualifierRange, - ArgumentDependentLookup, Overloaded, - HasExplicitTemplateArgs, ExplicitTemplateArgs); - + // Build an overload candidate set based on the functions we find. + OverloadCandidateSet CandidateSet; + // FIXME: What if we're calling something that isn't a function declaration? // FIXME: What if we're calling a pseudo-destructor? // FIXME: What if we're calling a member function? - // Build an overload candidate set based on the functions we find. - OverloadCandidateSet CandidateSet; - AddOverloadedCallCandidates(Fns, UnqualifiedName, - ArgumentDependentLookup, - (HasExplicitTemplateArgs ? &ExplicitTemplateArgs : 0), - Args, NumArgs, - CandidateSet, - /*PartialOverloading=*/true); + Expr *NakedFn = Fn->IgnoreParenCasts(); + if (UnresolvedLookupExpr *ULE = dyn_cast(NakedFn)) + AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet, + /*PartialOverloading=*/ true); + else if (DeclRefExpr *DRE = dyn_cast(NakedFn)) { + FunctionDecl *FDecl = dyn_cast(DRE->getDecl()); + if (FDecl) + AddOverloadCandidate(FDecl, Args, NumArgs, CandidateSet, + false, false, /*PartialOverloading*/ true); + } // Sort the overload candidate set by placing the best overloads first. std::stable_sort(CandidateSet.begin(), CandidateSet.end(), @@ -2419,7 +2453,6 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, typedef CodeCompleteConsumer::Result Result; Expr *RecExpr = static_cast(Receiver); - QualType RecType = RecExpr->getType(); // If necessary, apply function/array conversion to the receiver. // C99 6.7.5.3p[7,8]. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 14d2377..2253f09 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -35,6 +35,7 @@ #include "clang/Lex/HeaderSearch.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" #include #include #include @@ -106,8 +107,12 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(*SS)) return 0; } - - LookupResult Result(*this, &II, NameLoc, LookupOrdinaryName); + + // FIXME: LookupNestedNameSpecifierName isn't the right kind of + // lookup for class-names. + LookupNameKind Kind = isClassName ? LookupNestedNameSpecifierName : + LookupOrdinaryName; + LookupResult Result(*this, &II, NameLoc, Kind); if (LookupCtx) { // Perform "qualified" name lookup into the declaration context we // computed, which is either the type of the base of a member access @@ -250,10 +255,41 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, // We don't have anything to suggest (yet). SuggestedType = 0; + // There may have been a typo in the name of the type. Look up typo + // results, in case we have something that we can suggest. + LookupResult Lookup(*this, &II, IILoc, LookupOrdinaryName, + NotForRedeclaration); + + // FIXME: It would be nice if we could correct for typos in built-in + // names, such as "itn" for "int". + + if (CorrectTypo(Lookup, S, SS) && Lookup.isSingleResult()) { + NamedDecl *Result = Lookup.getAsSingle(); + if ((isa(Result) || isa(Result)) && + !Result->isInvalidDecl()) { + // We found a similarly-named type or interface; suggest that. + if (!SS || !SS->isSet()) + Diag(IILoc, diag::err_unknown_typename_suggest) + << &II << Lookup.getLookupName() + << CodeModificationHint::CreateReplacement(SourceRange(IILoc), + Result->getNameAsString()); + else if (DeclContext *DC = computeDeclContext(*SS, false)) + Diag(IILoc, diag::err_unknown_nested_typename_suggest) + << &II << DC << Lookup.getLookupName() << SS->getRange() + << CodeModificationHint::CreateReplacement(SourceRange(IILoc), + Result->getNameAsString()); + else + llvm_unreachable("could not have corrected a typo here"); + + SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS); + return true; + } + } + // FIXME: Should we move the logic that tries to recover from a missing tag // (struct, union, enum) from Parser::ParseImplicitInt here, instead? - if (!SS) + if (!SS || (!SS->isSet() && !SS->isInvalid())) Diag(IILoc, diag::err_unknown_typename) << &II; else if (DeclContext *DC = computeDeclContext(*SS, false)) Diag(IILoc, diag::err_typename_nested_not_found) @@ -321,23 +357,47 @@ void Sema::PopDeclContext() { /// EnterDeclaratorContext - Used when we must lookup names in the context /// of a declarator's nested name specifier. +/// void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) { - assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?"); - PreDeclaratorDC = static_cast(S->getEntity()); + // C++0x [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. + // C++0x [basic.lookup.unqual]p14: + // If a variable member of a namespace is defined outside of the + // scope of its namespace then any name used in the definition of + // the variable member (after the declarator-id) is looked up as + // if the definition of the variable member occurred in its + // namespace. + // Both of these imply that we should push a scope whose context + // is the semantic context of the declaration. We can't use + // PushDeclContext here because that context is not necessarily + // lexically contained in the current context. Fortunately, + // the containing scope should have the appropriate information. + + assert(!S->getEntity() && "scope already has entity"); + +#ifndef NDEBUG + Scope *Ancestor = S->getParent(); + while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent(); + assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch"); +#endif + CurContext = DC; - assert(CurContext && "No context?"); - S->setEntity(CurContext); + S->setEntity(DC); } void Sema::ExitDeclaratorContext(Scope *S) { - S->setEntity(PreDeclaratorDC); - PreDeclaratorDC = 0; + assert(S->getEntity() == CurContext && "Context imbalance!"); - // Reset CurContext to the nearest enclosing context. - while (!S->getEntity() && S->getParent()) - S = S->getParent(); - CurContext = static_cast(S->getEntity()); - assert(CurContext && "No context?"); + // Switch back to the lexical context. The safety of this is + // enforced by an assert in EnterDeclaratorContext. + Scope *Ancestor = S->getParent(); + while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent(); + CurContext = (DeclContext*) Ancestor->getEntity(); + + // We don't need to do anything with the scope, which is going to + // disappear. } /// \brief Determine whether we allow overloading of the function @@ -667,9 +727,8 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { } // Verify the old decl was also a type. - TypeDecl *Old = 0; - if (!OldDecls.isSingleResult() || - !(Old = dyn_cast(OldDecls.getFoundDecl()))) { + TypeDecl *Old = OldDecls.getAsSingle(); + if (!Old) { Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); @@ -704,6 +763,13 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { return New->setInvalidDecl(); } + // The types match. Link up the redeclaration chain if the old + // declaration was a typedef. + // FIXME: this is a potential source of wierdness if the type + // spellings don't match exactly. + if (isa(Old)) + New->setPreviousDeclaration(cast(Old)); + if (getLangOptions().Microsoft) return; @@ -772,7 +838,7 @@ static Sema::CXXSpecialMember getSpecialMember(ASTContext &Ctx, if (const CXXConstructorDecl *Ctor = dyn_cast(MD)) { if (Ctor->isDefaultConstructor()) return Sema::CXXDefaultConstructor; - if (Ctor->isCopyConstructor(Ctx)) + if (Ctor->isCopyConstructor()) return Sema::CXXCopyConstructor; } @@ -901,7 +967,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { // (C++98 8.3.5p3): // All declarations for a function shall agree exactly in both the // return type and the parameter-type-list. - if (OldQType == NewQType) + // attributes should be ignored when comparing. + if (Context.getNoReturnType(OldQType, false) == + Context.getNoReturnType(NewQType, false)) return MergeCompatibleFunctionDecls(New, Old); // Fall through for conflicting redeclarations and redefinitions. @@ -1253,11 +1321,6 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) { HasFakeEdge = true; continue; } - if (isa(S)) { - HasFakeEdge = true; - HasLiveReturn = true; - continue; - } bool NoReturnEdge = false; if (CallExpr *C = dyn_cast(S)) { Expr *CEE = C->getCallee()->IgnoreParenCasts(); @@ -1445,7 +1508,6 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) { Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { // FIXME: Error on auto/register at file scope // FIXME: Error on inline/virtual/explicit - // FIXME: Error on invalid restrict // FIXME: Warn on useless __thread // FIXME: Warn on useless const/volatile // FIXME: Warn on useless static/extern/typedef/private_extern/mutable @@ -1467,6 +1529,15 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { Tag = dyn_cast(TagD); } + if (unsigned TypeQuals = DS.getTypeQualifiers()) { + // Enforce C99 6.7.3p2: "Types other than pointer types derived from object + // or incomplete types shall not be restrict-qualified." + if (TypeQuals & DeclSpec::TQ_restrict) + Diag(DS.getRestrictSpecLoc(), + diag::err_typecheck_invalid_restrict_not_pointer_noarg) + << DS.getSourceRange(); + } + if (DS.isFriendSpecified()) { // If we're dealing with a class template decl, assume that the // template routines are handling it. @@ -1516,29 +1587,27 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { return DeclPtrTy::make(Tag); } -/// We are trying to introduce the given name into the given context; +/// We are trying to inject an anonymous member into the given scope; /// check if there's an existing declaration that can't be overloaded. /// /// \return true if this is a forbidden redeclaration -bool Sema::CheckRedeclaration(DeclContext *DC, - DeclarationName Name, - SourceLocation NameLoc, - unsigned diagnostic) { - LookupResult R(*this, Name, NameLoc, LookupOrdinaryName, - ForRedeclaration); - LookupQualifiedName(R, DC); - - if (R.empty()) return false; - - if (R.getResultKind() == LookupResult::Found && - isa(R.getFoundDecl())) +static bool CheckAnonMemberRedeclaration(Sema &SemaRef, + Scope *S, + DeclarationName Name, + SourceLocation NameLoc, + unsigned diagnostic) { + LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName, + Sema::ForRedeclaration); + if (!SemaRef.LookupName(R, S)) return false; + + if (R.getAsSingle()) return false; // Pick a representative declaration. - NamedDecl *PrevDecl = (*R.begin())->getUnderlyingDecl(); + NamedDecl *PrevDecl = R.getRepresentativeDecl()->getUnderlyingDecl(); - Diag(NameLoc, diagnostic) << Name; - Diag(PrevDecl->getLocation(), diag::note_previous_declaration); + SemaRef.Diag(NameLoc, diagnostic) << Name; + SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration); return true; } @@ -1570,8 +1639,8 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner, FEnd = AnonRecord->field_end(); F != FEnd; ++F) { if ((*F)->getDeclName()) { - if (CheckRedeclaration(Owner, (*F)->getDeclName(), - (*F)->getLocation(), diagKind)) { + if (CheckAnonMemberRedeclaration(*this, S, (*F)->getDeclName(), + (*F)->getLocation(), diagKind)) { // C++ [class.union]p2: // The names of the members of an anonymous union shall be // distinct from the names of any other entity in the @@ -1889,9 +1958,12 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, if (DeclContext *DC = computeDeclContext(D.getCXXScopeSpec(), true)) { // FIXME: Preserve type source info. QualType T = GetTypeFromParser(DS.getTypeRep()); - EnterDeclaratorContext(S, DC); + + DeclContext *SavedContext = CurContext; + CurContext = DC; T = RebuildTypeInCurrentInstantiation(T, D.getIdentifierLoc(), Name); - ExitDeclaratorContext(S); + CurContext = SavedContext; + if (T.isNull()) return DeclPtrTy(); DS.UpdateTypeRep(T.getAsOpaquePtr()); @@ -3364,7 +3436,16 @@ void Sema::CheckMain(FunctionDecl* FD) { unsigned nparams = FTP->getNumArgs(); assert(FD->getNumParams() == nparams); - if (nparams > 3) { + bool HasExtraParameters = (nparams > 3); + + // Darwin passes an undocumented fourth argument of type char**. If + // other platforms start sprouting these, the logic below will start + // getting shifty. + if (nparams == 4 && + Context.Target.getTriple().getOS() == llvm::Triple::Darwin) + HasExtraParameters = false; + + if (HasExtraParameters) { Diag(FD->getLocation(), diag::err_main_surplus_args) << nparams; FD->setInvalidDecl(true); nparams = 3; @@ -3375,7 +3456,7 @@ void Sema::CheckMain(FunctionDecl* FD) { QualType CharPP = Context.getPointerType(Context.getPointerType(Context.CharTy)); - QualType Expected[] = { Context.IntTy, CharPP, CharPP }; + QualType Expected[] = { Context.IntTy, CharPP, CharPP, CharPP }; for (unsigned i = 0; i < nparams; ++i) { QualType AT = FTP->getArgType(i); @@ -3504,6 +3585,18 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { Expr *Init = init.takeAs(); assert(Init && "missing initializer"); + // Capture the variable that is being initialized and the style of + // initialization. + InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); + + // FIXME: Poor source location information. + InitializationKind Kind + = DirectInit? InitializationKind::CreateDirect(VDecl->getLocation(), + Init->getLocStart(), + Init->getLocEnd()) + : InitializationKind::CreateCopy(VDecl->getLocation(), + Init->getLocStart()); + // Get the decls type and save a reference for later, since // CheckInitializerTypes may change it. QualType DclT = VDecl->getType(), SavT = DclT; @@ -3512,37 +3605,16 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { Diag(VDecl->getLocation(), diag::err_block_extern_cant_init); VDecl->setInvalidDecl(); } else if (!VDecl->isInvalidDecl()) { - if (VDecl->getType()->isReferenceType() - || isa(Init)) { - InitializedEntity Entity - = InitializedEntity::InitializeVariable(VDecl); - - // FIXME: Poor source location information. - InitializationKind Kind - = DirectInit? InitializationKind::CreateDirect(VDecl->getLocation(), - SourceLocation(), - SourceLocation()) - : InitializationKind::CreateCopy(VDecl->getLocation(), - SourceLocation()); - InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); - if (InitSeq) { - OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, (void**)&Init, 1), - &DclT); - if (Result.isInvalid()) { - VDecl->setInvalidDecl(); - return; - } - - Init = Result.takeAs(); - } else { - InitSeq.Diagnose(*this, Entity, Kind, &Init, 1); - VDecl->setInvalidDecl(); - return; - } - } else if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(), - VDecl->getDeclName(), DirectInit)) + InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); + OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, (void**)&Init, 1), + &DclT); + if (Result.isInvalid()) { VDecl->setInvalidDecl(); + return; + } + + Init = Result.takeAs(); // C++ 3.6.2p2, allow dynamic initialization of static initializers. // Don't check invalid declarations to avoid emitting useless diagnostics. @@ -3601,10 +3673,18 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { } else if (VDecl->isFileVarDecl()) { if (VDecl->getStorageClass() == VarDecl::Extern) Diag(VDecl->getLocation(), diag::warn_extern_init); - if (!VDecl->isInvalidDecl()) - if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(), - VDecl->getDeclName(), DirectInit)) + if (!VDecl->isInvalidDecl()) { + InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); + OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, (void**)&Init, 1), + &DclT); + if (Result.isInvalid()) { VDecl->setInvalidDecl(); + return; + } + + Init = Result.takeAs(); + } // C++ 3.6.2p2, allow dynamic initialization of static initializers. // Don't check invalid declarations to avoid emitting useless diagnostics. @@ -3622,8 +3702,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { Init->setType(DclT); } - Init = MaybeCreateCXXExprWithTemporaries(Init, - /*ShouldDestroyTemporaries=*/true); + Init = MaybeCreateCXXExprWithTemporaries(Init); // Attach the initializer to the decl. VDecl->setInit(Context, Init); @@ -3635,6 +3714,15 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { assert(Deleted && "Unrecorded tentative definition?"); Deleted=Deleted; } + if (getLangOptions().CPlusPlus) { + // Make sure we mark the destructor as used if necessary. + QualType InitType = VDecl->getType(); + if (const ArrayType *Array = Context.getAsArrayType(InitType)) + InitType = Context.getBaseElementType(Array); + if (InitType->isRecordType()) + FinalizeVarWithDestructor(VDecl, InitType); + } + return; } @@ -3722,28 +3810,19 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, InitType->isRecordType() && !InitType->isDependentType()) { if (!RequireCompleteType(Var->getLocation(), InitType, diag::err_invalid_incomplete_type_use)) { - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); - - CXXConstructorDecl *Constructor - = PerformInitializationByConstructor(InitType, - MultiExprArg(*this, 0, 0), - Var->getLocation(), - SourceRange(Var->getLocation(), - Var->getLocation()), - Var->getDeclName(), - InitializationKind::CreateDefault(Var->getLocation()), - ConstructorArgs); - - // FIXME: Location info for the variable initialization? - if (!Constructor) + InitializedEntity Entity + = InitializedEntity::InitializeVariable(Var); + InitializationKind Kind + = InitializationKind::CreateDefault(Var->getLocation()); + + InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); + OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, 0, 0)); + if (Init.isInvalid()) Var->setInvalidDecl(); else { - // FIXME: Cope with initialization of arrays - if (!Constructor->isTrivial() && - InitializeVarWithConstructor(Var, Constructor, - move_arg(ConstructorArgs))) - Var->setInvalidDecl(); - + Var->setInit(Context, + MaybeCreateCXXExprWithTemporaries(Init.takeAs())); FinalizeVarWithDestructor(Var, InitType); } } else { @@ -4382,6 +4461,10 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { if (Context.BuiltinInfo.isNoReturn(BuiltinID)) FD->addAttr(::new (Context) NoReturnAttr()); + if (Context.BuiltinInfo.isNoThrow(BuiltinID)) + FD->addAttr(::new (Context) NoThrowAttr()); + if (Context.BuiltinInfo.isConst(BuiltinID)) + FD->addAttr(::new (Context) ConstAttr()); } IdentifierInfo *Name = FD->getIdentifier(); @@ -4939,31 +5022,36 @@ void Sema::ActOnTagStartDefinition(Scope *S, DeclPtrTy TagD) { // Enter the tag context. PushDeclContext(S, Tag); +} - if (CXXRecordDecl *Record = dyn_cast(Tag)) { - FieldCollector->StartClass(); - - if (Record->getIdentifier()) { - // C++ [class]p2: - // [...] The class-name is also inserted into the scope of the - // class itself; this is known as the injected-class-name. For - // purposes of access checking, the injected-class-name is treated - // as if it were a public member name. - CXXRecordDecl *InjectedClassName - = CXXRecordDecl::Create(Context, Record->getTagKind(), - CurContext, Record->getLocation(), - Record->getIdentifier(), - Record->getTagKeywordLoc(), - Record); - InjectedClassName->setImplicit(); - InjectedClassName->setAccess(AS_public); - if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) - InjectedClassName->setDescribedClassTemplate(Template); - PushOnScopeChains(InjectedClassName, S); - assert(InjectedClassName->isInjectedClassName() && - "Broken injected-class-name"); - } - } +void Sema::ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagD, + SourceLocation LBraceLoc) { + AdjustDeclIfTemplate(TagD); + CXXRecordDecl *Record = cast(TagD.getAs()); + + FieldCollector->StartClass(); + + if (!Record->getIdentifier()) + return; + + // C++ [class]p2: + // [...] The class-name is also inserted into the scope of the + // class itself; this is known as the injected-class-name. For + // purposes of access checking, the injected-class-name is treated + // as if it were a public member name. + CXXRecordDecl *InjectedClassName + = CXXRecordDecl::Create(Context, Record->getTagKind(), + CurContext, Record->getLocation(), + Record->getIdentifier(), + Record->getTagKeywordLoc(), + Record); + InjectedClassName->setImplicit(); + InjectedClassName->setAccess(AS_public); + if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) + InjectedClassName->setDescribedClassTemplate(Template); + PushOnScopeChains(InjectedClassName, S); + assert(InjectedClassName->isInjectedClassName() && + "Broken injected-class-name"); } void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD, @@ -5808,7 +5896,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, const llvm::APSInt &InitVal = ECD->getInitVal(); assert(InitVal.getBitWidth() >= IntWidth && "Should have promoted value to int"); - if (InitVal.getBitWidth() > IntWidth) { + if (!getLangOptions().CPlusPlus && InitVal.getBitWidth() > IntWidth) { llvm::APSInt V(InitVal); V.trunc(IntWidth); V.extend(InitVal.getBitWidth()); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 84ee207..094e5b5 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -47,7 +47,7 @@ static const FunctionType *getFunctionType(const Decl *d, // FIXME: We should provide an abstraction around a method or function // to provide the following bits of information. -/// isFunctionOrMethod - Return true if the given decl has function +/// isFunction - Return true if the given decl has function /// type (function or function-typed variable). static bool isFunction(const Decl *d) { return getFunctionType(d, false) != NULL; @@ -730,15 +730,19 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) return; } - // TODO: could also be applied to methods? - FunctionDecl *Fn = dyn_cast(D); - if (!Fn) { + if (!isFunctionOrMethod(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << 0 /*function*/; return; } - Fn->addAttr(::new (S.Context) WarnUnusedResultAttr()); + if (getFunctionType(D)->getResultType()->isVoidType()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_void_function) + << Attr.getName(); + return; + } + + D->addAttr(::new (S.Context) WarnUnusedResultAttr()); } static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -1610,7 +1614,10 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; return; } - NewTy = S.Context.getFixedWidthIntType(128, OldTy->isSignedIntegerType()); + if (OldTy->isSignedIntegerType()) + NewTy = S.Context.Int128Ty; + else + NewTy = S.Context.UnsignedInt128Ty; break; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 228a716..204d776 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -109,8 +109,6 @@ 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(); @@ -125,11 +123,17 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg, // 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)) + InitializedEntity Entity = InitializedEntity::InitializeParameter(Param); + InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(), + EqualLoc); + InitializationSequence InitSeq(*this, Entity, Kind, &Arg, 1); + OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, (void**)&Arg, 1)); + if (Result.isInvalid()) return true; + Arg = Result.takeAs(); - Arg = MaybeCreateCXXExprWithTemporaries(Arg, /*DestroyTemps=*/false); + Arg = MaybeCreateCXXExprWithTemporaries(Arg); // Okay: add the default argument to the parameter Param->setDefaultArg(Arg); @@ -152,7 +156,6 @@ Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc, UnparsedDefaultArgLocs.erase(Param); ExprOwningPtr DefaultArg(this, defarg.takeAs()); - QualType ParamType = Param->getType(); // Default arguments are only permitted in C++ if (!getLangOptions().CPlusPlus) { @@ -945,6 +948,51 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, return DeclPtrTy::make(Member); } +/// \brief Find the direct and/or virtual base specifiers that +/// correspond to the given base type, for use in base initialization +/// within a constructor. +static bool FindBaseInitializer(Sema &SemaRef, + CXXRecordDecl *ClassDecl, + QualType BaseType, + const CXXBaseSpecifier *&DirectBaseSpec, + const CXXBaseSpecifier *&VirtualBaseSpec) { + // First, check for a direct base class. + DirectBaseSpec = 0; + for (CXXRecordDecl::base_class_const_iterator Base + = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base->getType())) { + // 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. + 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 (SemaRef.IsDerivedFrom(SemaRef.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; + } + } + } + } + + return DirectBaseSpec || VirtualBaseSpec; +} + /// ActOnMemInitializer - Handle a C++ member initializer. Sema::MemInitResult Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, @@ -1000,16 +1048,69 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, } // It didn't name a member, so see if it names a class. QualType BaseType; - TypeSourceInfo *TInfo = 0; - if (TemplateTypeTy) + + if (TemplateTypeTy) { BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo); - else - BaseType = QualType::getFromOpaquePtr(getTypeName(*MemberOrBase, IdLoc, - S, &SS)); - if (BaseType.isNull()) - return Diag(IdLoc, diag::err_mem_init_not_member_or_class) - << MemberOrBase << SourceRange(IdLoc, RParenLoc); + } else { + LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName); + LookupParsedName(R, S, &SS); + + TypeDecl *TyD = R.getAsSingle(); + if (!TyD) { + if (R.isAmbiguous()) return true; + + // If no results were found, try to correct typos. + if (R.empty() && + CorrectTypo(R, S, &SS, ClassDecl) && R.isSingleResult()) { + if (FieldDecl *Member = R.getAsSingle()) { + if (Member->getDeclContext()->getLookupContext()->Equals(ClassDecl)) { + // We have found a non-static data member with a similar + // name to what was typed; complain and initialize that + // member. + Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest) + << MemberOrBase << true << R.getLookupName() + << CodeModificationHint::CreateReplacement(R.getNameLoc(), + R.getLookupName().getAsString()); + + return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc, + LParenLoc, RParenLoc); + } + } else if (TypeDecl *Type = R.getAsSingle()) { + const CXXBaseSpecifier *DirectBaseSpec; + const CXXBaseSpecifier *VirtualBaseSpec; + if (FindBaseInitializer(*this, ClassDecl, + Context.getTypeDeclType(Type), + DirectBaseSpec, VirtualBaseSpec)) { + // We have found a direct or virtual base class with a + // similar name to what was typed; complain and initialize + // that base class. + Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest) + << MemberOrBase << false << R.getLookupName() + << CodeModificationHint::CreateReplacement(R.getNameLoc(), + R.getLookupName().getAsString()); + + TyD = Type; + } + } + } + + if (!TyD) { + Diag(IdLoc, diag::err_mem_init_not_member_or_class) + << MemberOrBase << SourceRange(IdLoc, RParenLoc); + return true; + } + } + + BaseType = Context.getTypeDeclType(TyD); + if (SS.isSet()) { + NestedNameSpecifier *Qualifier = + static_cast(SS.getScopeRep()); + + // FIXME: preserve source range information + BaseType = Context.getQualifiedNameType(Qualifier, BaseType); + } + } if (!TInfo) TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc); @@ -1095,14 +1196,13 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, QualType FieldType = Member->getType(); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) FieldType = Array->getElementType(); + ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); if (FieldType->isDependentType()) { // Can't check init for dependent type. } else if (FieldType->isRecordType()) { // Member is a record (struct/union/class), so pass the initializer // arguments down to the record's constructor. if (!HasDependentArg) { - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); - C = PerformInitializationByConstructor(FieldType, MultiExprArg(*this, (void**)Args, @@ -1137,7 +1237,8 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, } else NewExp = (Expr*)Args[0]; - if (PerformCopyInitialization(NewExp, FieldType, "passing")) + if (!Member->isInvalidDecl() && + PerformCopyInitialization(NewExp, FieldType, AA_Passing)) return true; Args[0] = NewExp; } @@ -1174,37 +1275,11 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, // mem-initializer-list can initialize a base class using any // name that denotes that base class type. - // First, check for a direct base class. + // Check for direct and virtual base classes. const CXXBaseSpecifier *DirectBaseSpec = 0; - for (CXXRecordDecl::base_class_const_iterator Base = - ClassDecl->bases_begin(); Base != ClassDecl->bases_end(); ++Base) { - if (Context.hasSameUnqualifiedType(BaseType, Base->getType())) { - // 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; - } - } - } - } + FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, + VirtualBaseSpec); // C++ [base.class.init]p2: // If a mem-initializer-id is ambiguous because it designates both @@ -1224,10 +1299,10 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, } CXXConstructorDecl *C = 0; + ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); if (!BaseType->isDependentType() && !HasDependentArg) { DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(BaseType).getUnqualifiedType()); - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); C = PerformInitializationByConstructor(BaseType, MultiExprArg(*this, @@ -1977,6 +2052,12 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { if (!Record || Record->isInvalidDecl()) return; + if (!Record->isDependentType()) + AddImplicitlyDeclaredMembersToClass(Record); + + if (Record->isInvalidDecl()) + return; + if (!Record->isAbstract()) { // Collect all the pure virtual methods and see if this is an abstract // class after all. @@ -1987,9 +2068,6 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { if (Record->isAbstract()) (void)AbstractClassUsageDiagnoser(*this, Record); - - if (!Record->isDependentType() && !Record->isInvalidDecl()) - AddImplicitlyDeclaredMembersToClass(Record); } void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, @@ -2261,6 +2339,18 @@ void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) { } } +void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) { + if (!RecordD) return; + AdjustDeclIfTemplate(RecordD); + CXXRecordDecl *Record = cast(RecordD.getAs()); + PushDeclContext(S, Record); +} + +void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) { + if (!RecordD) return; + PopDeclContext(); +} + /// ActOnStartDelayedCXXMethodDeclaration - We have completed /// parsing a top-level (non-nested) C++ class, and we are now /// parsing those parts of the given Method declaration that could @@ -2270,18 +2360,6 @@ void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) { /// name. However, it should not bring the parameters into scope; /// that will be performed by ActOnDelayedCXXMethodParameter. void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) { - if (!MethodD) - return; - - AdjustDeclIfTemplate(MethodD); - - CXXScopeSpec SS; - FunctionDecl *Method = cast(MethodD.getAs()); - QualType ClassTy - = Context.getTypeDeclType(cast(Method->getDeclContext())); - SS.setScopeRep( - NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr())); - ActOnCXXEnterDeclaratorScope(S, SS); } /// ActOnDelayedCXXMethodParameter - We've already started a delayed @@ -2318,12 +2396,6 @@ void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) { AdjustDeclIfTemplate(MethodD); FunctionDecl *Method = cast(MethodD.getAs()); - CXXScopeSpec SS; - QualType ClassTy - = Context.getTypeDeclType(cast(Method->getDeclContext())); - SS.setScopeRep( - NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr())); - ActOnCXXExitDeclaratorScope(S, SS); // Now that we have our default arguments, check the constructor // again. It could produce additional diagnostics or affect whether @@ -2746,6 +2818,28 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, PushOnScopeChains(Namespc, DeclRegionScope); } else { // Anonymous namespaces. + assert(Namespc->isAnonymousNamespace()); + CurContext->addDecl(Namespc); + + // Link the anonymous namespace into its parent. + NamespaceDecl *PrevDecl; + DeclContext *Parent = CurContext->getLookupContext(); + if (TranslationUnitDecl *TU = dyn_cast(Parent)) { + PrevDecl = TU->getAnonymousNamespace(); + TU->setAnonymousNamespace(Namespc); + } else { + NamespaceDecl *ND = cast(Parent); + PrevDecl = ND->getAnonymousNamespace(); + ND->setAnonymousNamespace(Namespc); + } + + // Link the anonymous namespace with its previous declaration. + if (PrevDecl) { + assert(PrevDecl->isAnonymousNamespace()); + assert(!PrevDecl->getNextNamespace()); + Namespc->setOriginalNamespace(PrevDecl->getOriginalNamespace()); + PrevDecl->setNextNamespace(Namespc); + } // C++ [namespace.unnamed]p1. An unnamed-namespace-definition // behaves as if it were replaced by @@ -2763,20 +2857,19 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // 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); + if (!PrevDecl) { + 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 @@ -3696,7 +3789,7 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *CopyConstructor, unsigned TypeQuals) { assert((CopyConstructor->isImplicit() && - CopyConstructor->isCopyConstructor(Context, TypeQuals) && + CopyConstructor->isCopyConstructor(TypeQuals) && !CopyConstructor->isUsed()) && "DefineImplicitCopyConstructor - call it for implicit copy ctor"); @@ -3736,7 +3829,8 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, Sema::OwningExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, - MultiExprArg ExprArgs) { + MultiExprArg ExprArgs, + bool RequiresZeroInit) { bool Elidable = false; // C++ [class.copy]p15: @@ -3747,8 +3841,13 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, // all, even if the class copy constructor or destructor have side effects. // FIXME: Is this enough? - if (Constructor->isCopyConstructor(Context)) { + if (Constructor->isCopyConstructor()) { Expr *E = ((Expr **)ExprArgs.get())[0]; + if (ImplicitCastExpr *ICE = dyn_cast(E)) + if (ICE->getCastKind() == CastExpr::CK_NoOp) + E = ICE->getSubExpr(); + if (CXXFunctionalCastExpr *FCE = dyn_cast(E)) + E = FCE->getSubExpr(); while (CXXBindTemporaryExpr *BE = dyn_cast(E)) E = BE->getSubExpr(); if (ImplicitCastExpr *ICE = dyn_cast(E)) @@ -3759,10 +3858,12 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, Elidable = !CE->getCallReturnType()->isReferenceType(); else if (isa(E)) Elidable = true; + else if (isa(E)) + Elidable = true; } return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, - Elidable, move(ExprArgs)); + Elidable, move(ExprArgs), RequiresZeroInit); } /// BuildCXXConstructExpr - Creates a complete call to a constructor, @@ -3770,13 +3871,15 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, Sema::OwningExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, - MultiExprArg ExprArgs) { + MultiExprArg ExprArgs, + bool RequiresZeroInit) { unsigned NumExprs = ExprArgs.size(); Expr **Exprs = (Expr **)ExprArgs.release(); MarkDeclarationReferenced(ConstructLoc, Constructor); - return Owned(CXXConstructExpr::Create(Context, DeclInitType, Constructor, - Elidable, Exprs, NumExprs)); + return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, + Constructor, Elidable, Exprs, NumExprs, + RequiresZeroInit)); } Sema::OwningExprResult @@ -3806,7 +3909,7 @@ bool Sema::InitializeVarWithConstructor(VarDecl *VD, Expr *Temp = TempResult.takeAs(); MarkDeclarationReferenced(VD->getLocation(), Constructor); - Temp = MaybeCreateCXXExprWithTemporaries(Temp, /*DestroyTemps=*/true); + Temp = MaybeCreateCXXExprWithTemporaries(Temp); VD->setInit(Context, Temp); return false; @@ -3829,8 +3932,7 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, MultiExprArg Exprs, SourceLocation *CommaLocs, SourceLocation RParenLoc) { - unsigned NumExprs = Exprs.size(); - assert(NumExprs != 0 && Exprs.get() && "missing expressions"); + assert(Exprs.size() != 0 && Exprs.get() && "missing expressions"); Decl *RealDecl = Dcl.getAs(); // If there is no declaration, there was an error parsing it. Just ignore @@ -3881,53 +3983,50 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, if (const ArrayType *Array = Context.getAsArrayType(DeclInitType)) DeclInitType = Context.getBaseElementType(Array); - // FIXME: This isn't the right place to complete the type. if (RequireCompleteType(VDecl->getLocation(), VDecl->getType(), diag::err_typecheck_decl_incomplete_type)) { VDecl->setInvalidDecl(); return; } - if (VDecl->getType()->isRecordType()) { - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); - - CXXConstructorDecl *Constructor - = PerformInitializationByConstructor(DeclInitType, - move(Exprs), - VDecl->getLocation(), - SourceRange(VDecl->getLocation(), - RParenLoc), - VDecl->getDeclName(), - InitializationKind::CreateDirect(VDecl->getLocation(), - LParenLoc, - RParenLoc), - ConstructorArgs); - if (!Constructor) - RealDecl->setInvalidDecl(); - else { - VDecl->setCXXDirectInitializer(true); - if (InitializeVarWithConstructor(VDecl, Constructor, - move_arg(ConstructorArgs))) - RealDecl->setInvalidDecl(); - FinalizeVarWithDestructor(VDecl, DeclInitType); - } + // The variable can not have an abstract class type. + if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(), + diag::err_abstract_type_in_decl, + AbstractVariableType)) + VDecl->setInvalidDecl(); + + const VarDecl *Def = 0; + if (VDecl->getDefinition(Def)) { + Diag(VDecl->getLocation(), diag::err_redefinition) + << VDecl->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); + VDecl->setInvalidDecl(); return; } - - if (NumExprs > 1) { - Diag(CommaLocs[0], diag::err_builtin_direct_init_more_than_one_arg) - << SourceRange(VDecl->getLocation(), RParenLoc); - RealDecl->setInvalidDecl(); + + // Capture the variable that is being initialized and the style of + // initialization. + InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); + + // FIXME: Poor source location information. + InitializationKind Kind + = InitializationKind::CreateDirect(VDecl->getLocation(), + LParenLoc, RParenLoc); + + InitializationSequence InitSeq(*this, Entity, Kind, + (Expr**)Exprs.get(), Exprs.size()); + OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(Exprs)); + if (Result.isInvalid()) { + VDecl->setInvalidDecl(); return; } - - // Let clients know that initialization was done with a direct initializer. + + Result = MaybeCreateCXXExprWithTemporaries(move(Result)); + VDecl->setInit(Context, Result.takeAs()); VDecl->setCXXDirectInitializer(true); - assert(NumExprs == 1 && "Expected 1 expression"); - // Set the init expression, handles conversions. - AddInitializerToDecl(Dcl, ExprArg(*this, Exprs.release()[0]), - /*DirectInit=*/true); + if (VDecl->getType()->getAs()) + FinalizeVarWithDestructor(VDecl, DeclInitType); } /// \brief Add the applicable constructor candidates for an initialization @@ -4164,7 +4263,7 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, /// type, and the first type (T1) is the pointee type of the reference /// type being initialized. Sema::ReferenceCompareResult -Sema::CompareReferenceRelationship(SourceLocation Loc, +Sema::CompareReferenceRelationship(SourceLocation Loc, QualType OrigT1, QualType OrigT2, bool& DerivedToBase) { assert(!OrigT1->isReferenceType() && @@ -4173,8 +4272,9 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, QualType T1 = Context.getCanonicalType(OrigT1); QualType T2 = Context.getCanonicalType(OrigT2); - QualType UnqualT1 = T1.getLocalUnqualifiedType(); - QualType UnqualT2 = T2.getLocalUnqualifiedType(); + Qualifiers T1Quals, T2Quals; + QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals); + QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals); // C++ [dcl.init.ref]p4: // Given types "cv1 T1" and "cv2 T2," "cv1 T1" is @@ -4192,6 +4292,13 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, // At this point, we know that T1 and T2 are reference-related (at // least). + // If the type is an array type, promote the element qualifiers to the type + // for comparison. + if (isa(T1) && T1Quals) + T1 = Context.getQualifiedType(UnqualT1, T1Quals); + if (isa(T2) && T2Quals) + T2 = Context.getQualifiedType(UnqualT2, T2Quals); + // C++ [dcl.init.ref]p4: // "cv1 T1" is reference-compatible with "cv2 T2" if T1 is // reference-related to T2 and cv1 is the same cv-qualification @@ -4199,7 +4306,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, // overload resolution, cases for which cv1 is greater // cv-qualification than cv2 are identified as // reference-compatible with added qualification (see 13.3.3.2). - if (T1.getCVRQualifiers() == T2.getCVRQualifiers()) + if (T1Quals.getCVRQualifiers() == T2Quals.getCVRQualifiers()) return Ref_Compatible; else if (T1.isMoreQualifiedThan(T2)) return Ref_Compatible_With_Added_Qualification; @@ -4462,7 +4569,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const) { if (!ICS) Diag(DeclLoc, diag::err_not_reference_to_const_init) - << T1 << (InitLvalue != Expr::LV_Valid? "temporary" : "value") + << T1 << int(InitLvalue != Expr::LV_Valid) << T2 << Init->getSourceRange(); return true; } @@ -4528,7 +4635,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, // initialization fails. if (!ICS) Diag(DeclLoc, diag::err_reference_init_drops_quals) - << T1 << (InitLvalue != Expr::LV_Valid? "temporary" : "value") + << T1 << int(InitLvalue != Expr::LV_Valid) << T2 << Init->getSourceRange(); return true; } @@ -4542,7 +4649,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, (T1->isRecordType() || T2->isRecordType())) { if (!ICS) Diag(DeclLoc, diag::err_typecheck_convert_incompatible) - << DeclType << Init->getType() << "initializing" << Init->getSourceRange(); + << DeclType << Init->getType() << AA_Initializing << Init->getSourceRange(); return true; } @@ -4576,7 +4683,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, return ICS->ConversionKind == ImplicitConversionSequence::BadConversion; } else { ImplicitConversionSequence Conversions; - bool badConversion = PerformImplicitConversion(Init, T1, "initializing", + bool badConversion = PerformImplicitConversion(Init, T1, AA_Initializing, false, false, Conversions); if (badConversion) { @@ -4664,7 +4771,7 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, << FnDecl->getDeclName() << ExpectedFirstParamType; // Check that the first parameter type is what we expect. - if (SemaRef.Context.getCanonicalType(FirstParamType) != + if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() != ExpectedFirstParamType) return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag) << FnDecl->getDeclName() << ExpectedFirstParamType; @@ -5154,13 +5261,10 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, // 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()) - if (RT->getDecl()->getDeclContext() == CurContext) - Diag(DS.getFriendSpecLoc(), diag::ext_friend_inner_class); + // This is fixed in DR77, which just barely didn't make the C++03 + // deadline. It's also a very silly restriction that seriously + // affects inner classes and which nobody else seems to implement; + // thus we never diagnose it, not even in -pedantic. Decl *D; if (TempParams.size()) @@ -5341,6 +5445,9 @@ Sema::ActOnFriendFunctionDecl(Scope *S, FrD->setAccess(AS_public); CurContext->addDecl(FrD); + if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) + FrD->setSpecialization(true); + return DeclPtrTy::make(ND); } @@ -5421,6 +5528,18 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, return true; } + // C++ [class.virtual]p6: + // If the return type of D::f differs from the return type of B::f, the + // class type in the return type of D::f shall be complete at the point of + // declaration of D::f or shall be the class type D. + if (const RecordType *RT = NewClassTy->getAs()) { + if (!RT->isBeingDefined() && + RequireCompleteType(New->getLocation(), NewClassTy, + PDiag(diag::err_covariant_return_incomplete) + << New->getDeclName())) + return true; + } + if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) { // Check if the new class derives from the old class. if (!IsDerivedFrom(NewClassTy, OldClassTy)) { @@ -5497,50 +5616,32 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) { return true; } -/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an -/// initializer for the declaration 'Dcl'. +/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse +/// an initializer for the out-of-line declaration 'Dcl'. The scope +/// is a fresh scope pushed for just this purpose. +/// /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a /// static data member of class X, names should be looked up in the scope of /// class X. void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) { - AdjustDeclIfTemplate(Dcl); - - Decl *D = Dcl.getAs(); // If there is no declaration, there was an error parsing it. - if (D == 0) - return; - - // Check whether it is a declaration with a nested name specifier like - // int foo::bar; - if (!D->isOutOfLine()) - return; - - // 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. + Decl *D = Dcl.getAs(); + if (D == 0) return; - // Change current context into the context of the initializing declaration. + // We should only get called for declarations with scope specifiers, like: + // int foo::bar; + assert(D->isOutOfLine()); EnterDeclaratorContext(S, D->getDeclContext()); } /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an -/// initializer for the declaration 'Dcl'. +/// initializer for the out-of-line declaration 'Dcl'. void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) { - AdjustDeclIfTemplate(Dcl); - - Decl *D = Dcl.getAs(); // If there is no declaration, there was an error parsing it. - if (D == 0) - return; - - // Check whether it is a declaration with a nested name specifier like - // int foo::bar; - if (!D->isOutOfLine()) - return; + Decl *D = Dcl.getAs(); + if (D == 0) return; - assert(S->getEntity() == D->getDeclContext() && "Context imbalance!"); + assert(D->isOutOfLine()); ExitDeclaratorContext(S); } diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index a768e1b..beadb58 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1950,6 +1950,10 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, !(Attributes & ObjCDeclSpec::DQ_PR_retain) && !(Attributes & ObjCDeclSpec::DQ_PR_copy))); QualType T = GetTypeForDeclarator(FD.D, S); + if (T->isReferenceType()) { + Diag(AtLoc, diag::error_reference_property); + return DeclPtrTy(); + } Decl *ClassDecl = ClassCategory.getAs(); ObjCInterfaceDecl *CCPrimary = 0; // continuation class's primary class // May modify Attributes. @@ -2028,7 +2032,14 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(), FD.D.getIdentifier(), T); - DC->addDecl(PDecl); + DeclContext::lookup_result Found = DC->lookup(PDecl->getDeclName()); + if (Found.first != Found.second && isa(*Found.first)) { + Diag(PDecl->getLocation(), diag::err_duplicate_property); + Diag((*Found.first)->getLocation(), diag::note_property_declare); + PDecl->setInvalidDecl(); + } + else + DC->addDecl(PDecl); if (T->isArrayType() || T->isFunctionType()) { Diag(AtLoc, diag::err_property_type) << T; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 358f445..7bf04d8 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "SemaInit.h" #include "Lookup.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -258,44 +259,17 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) { bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) { DefaultArgumentPromotion(Expr); - if (Expr->getType()->isObjCInterfaceType()) { - switch (ExprEvalContexts.back().Context ) { - case Unevaluated: - // The argument will never be evaluated, so don't complain. - break; - - case PotentiallyEvaluated: - Diag(Expr->getLocStart(), - diag::err_cannot_pass_objc_interface_to_vararg) - << Expr->getType() << CT; - return true; - - case PotentiallyPotentiallyEvaluated: - ExprEvalContexts.back().addDiagnostic(Expr->getLocStart(), - PDiag(diag::err_cannot_pass_objc_interface_to_vararg) - << Expr->getType() << CT); - break; - } - } - - if (!Expr->getType()->isPODType()) { - switch (ExprEvalContexts.back().Context ) { - case Unevaluated: - // The argument will never be evaluated, so don't complain. - break; - - case PotentiallyEvaluated: - Diag(Expr->getLocStart(), diag::warn_cannot_pass_non_pod_arg_to_vararg) - << Expr->getType() << CT; - break; + if (Expr->getType()->isObjCInterfaceType() && + DiagRuntimeBehavior(Expr->getLocStart(), + PDiag(diag::err_cannot_pass_objc_interface_to_vararg) + << Expr->getType() << CT)) + return true; - case PotentiallyPotentiallyEvaluated: - ExprEvalContexts.back().addDiagnostic(Expr->getLocStart(), - PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) - << Expr->getType() << CT); - break; - } - } + if (!Expr->getType()->isPODType() && + DiagRuntimeBehavior(Expr->getLocStart(), + PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) + << Expr->getType() << CT)) + return true; return false; } @@ -590,7 +564,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, == Context.getCanonicalType(ThisType)) || IsDerivedFrom(ThisType, AnonFieldType)) { // Our base object expression is "this". - BaseObjectExpr = new (Context) CXXThisExpr(SourceLocation(), + BaseObjectExpr = new (Context) CXXThisExpr(Loc, MD->getThisType(Context)); BaseObjectIsPointer = true; } @@ -761,23 +735,9 @@ static bool IsProvablyNotDerivedFrom(Sema &SemaRef, return true; } -/// Determines if this a C++ class member. -static bool IsClassMember(NamedDecl *D) { - DeclContext *DC = D->getDeclContext(); - - // C++0x [class.mem]p1: - // The enumerators of an unscoped enumeration defined in - // the class are members of the class. - // FIXME: support C++0x scoped enumerations. - if (isa(DC)) - DC = DC->getParent(); - - return DC->isRecord(); -} - /// Determines if this is an instance member of a class. static bool IsInstanceMember(NamedDecl *D) { - assert(IsClassMember(D) && + assert(D->isCXXClassMember() && "checking whether non-member is instance member"); if (isa(D)) return true; @@ -839,7 +799,7 @@ enum IMAKind { /// not be caught until template-instantiation. static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, const LookupResult &R) { - assert(!R.empty() && IsClassMember(*R.begin())); + assert(!R.empty() && (*R.begin())->isCXXClassMember()); bool isStaticContext = (!isa(SemaRef.CurContext) || @@ -916,6 +876,112 @@ static void DiagnoseInstanceReference(Sema &SemaRef, SemaRef.Diag(Loc, diag::err_member_call_without_object) << Range; } +/// Diagnose an empty lookup. +/// +/// \return false if new lookup candidates were found +bool Sema::DiagnoseEmptyLookup(Scope *S, const CXXScopeSpec &SS, + LookupResult &R) { + DeclarationName Name = R.getLookupName(); + + unsigned diagnostic = diag::err_undeclared_var_use; + unsigned diagnostic_suggest = diag::err_undeclared_var_use_suggest; + if (Name.getNameKind() == DeclarationName::CXXOperatorName || + Name.getNameKind() == DeclarationName::CXXLiteralOperatorName || + Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { + diagnostic = diag::err_undeclared_use; + diagnostic_suggest = diag::err_undeclared_use_suggest; + } + + // If the original lookup was an unqualified lookup, fake an + // unqualified lookup. This is useful when (for example) the + // original lookup would not have found something because it was a + // dependent name. + for (DeclContext *DC = SS.isEmpty()? CurContext : 0; + DC; DC = DC->getParent()) { + if (isa(DC)) { + LookupQualifiedName(R, DC); + + if (!R.empty()) { + // Don't give errors about ambiguities in this lookup. + R.suppressDiagnostics(); + + CXXMethodDecl *CurMethod = dyn_cast(CurContext); + bool isInstance = CurMethod && + CurMethod->isInstance() && + DC == CurMethod->getParent(); + + // Give a code modification hint to insert 'this->'. + // TODO: fixit for inserting 'Base::' in the other cases. + // Actually quite difficult! + if (isInstance) + Diag(R.getNameLoc(), diagnostic) << Name + << CodeModificationHint::CreateInsertion(R.getNameLoc(), + "this->"); + else + Diag(R.getNameLoc(), diagnostic) << Name; + + // Do we really want to note all of these? + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + Diag((*I)->getLocation(), diag::note_dependent_var_use); + + // Tell the callee to try to recover. + return false; + } + } + } + + // We didn't find anything, so try to correct for a typo. + if (S && CorrectTypo(R, S, &SS)) { + if (isa(*R.begin()) || isa(*R.begin())) { + if (SS.isEmpty()) + Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName() + << CodeModificationHint::CreateReplacement(R.getNameLoc(), + R.getLookupName().getAsString()); + else + Diag(R.getNameLoc(), diag::err_no_member_suggest) + << Name << computeDeclContext(SS, false) << R.getLookupName() + << SS.getRange() + << CodeModificationHint::CreateReplacement(R.getNameLoc(), + R.getLookupName().getAsString()); + + // Tell the callee to try to recover. + return false; + } + + if (isa(*R.begin()) || isa(*R.begin())) { + // FIXME: If we ended up with a typo for a type name or + // Objective-C class name, we're in trouble because the parser + // is in the wrong place to recover. Suggest the typo + // correction, but don't make it a fix-it since we're not going + // to recover well anyway. + if (SS.isEmpty()) + Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName(); + else + Diag(R.getNameLoc(), diag::err_no_member_suggest) + << Name << computeDeclContext(SS, false) << R.getLookupName() + << SS.getRange(); + + // Don't try to recover; it won't work. + return true; + } + + R.clear(); + } + + // Emit a special diagnostic for failed member lookups. + // FIXME: computing the declaration context might fail here (?) + if (!SS.isEmpty()) { + Diag(R.getNameLoc(), diag::err_no_member) + << Name << computeDeclContext(SS, false) + << SS.getRange(); + return true; + } + + // Give up, we can't recover. + Diag(R.getNameLoc(), diagnostic) << Name; + return true; +} + Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, const CXXScopeSpec &SS, UnqualifiedId &Id, @@ -988,17 +1054,11 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, // If this name wasn't predeclared and if this is not a function // call, diagnose the problem. if (R.empty()) { - if (!SS.isEmpty()) - return ExprError(Diag(NameLoc, diag::err_no_member) - << Name << computeDeclContext(SS, false) - << SS.getRange()); - else if (Name.getNameKind() == DeclarationName::CXXOperatorName || - Name.getNameKind() == DeclarationName::CXXLiteralOperatorName || - Name.getNameKind() == DeclarationName::CXXConversionFunctionName) - return ExprError(Diag(NameLoc, diag::err_undeclared_use) - << Name); - else - return ExprError(Diag(NameLoc, diag::err_undeclared_var_use) << Name); + if (DiagnoseEmptyLookup(S, SS, R)) + return ExprError(); + + assert(!R.empty() && + "DiagnoseEmptyLookup returned false but added no results"); } } @@ -1051,35 +1111,10 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, // class member access expression. // But note that &SomeClass::foo is grammatically distinct, even // though we don't parse it that way. - if (!R.empty() && IsClassMember(*R.begin())) { + if (!R.empty() && (*R.begin())->isCXXClassMember()) { bool isAbstractMemberPointer = (isAddressOfOperand && !SS.isEmpty()); - - if (!isAbstractMemberPointer) { - switch (ClassifyImplicitMemberAccess(*this, R)) { - case IMA_Instance: - return BuildImplicitMemberExpr(SS, R, TemplateArgs, true); - - case IMA_AnonymousMember: - assert(R.isSingleResult()); - return BuildAnonymousStructUnionMemberReference(R.getNameLoc(), - R.getAsSingle()); - - case IMA_Mixed: - case IMA_Mixed_Unrelated: - case IMA_Unresolved: - return BuildImplicitMemberExpr(SS, R, TemplateArgs, false); - - case IMA_Static: - case IMA_Mixed_StaticContext: - case IMA_Unresolved_StaticContext: - break; - - case IMA_Error_StaticContext: - case IMA_Error_Unrelated: - DiagnoseInstanceReference(*this, SS, R); - return ExprError(); - } - } + if (!isAbstractMemberPointer) + return BuildPossibleImplicitMemberExpr(SS, R, TemplateArgs); } if (TemplateArgs) @@ -1088,6 +1123,42 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, return BuildDeclarationNameExpr(SS, R, ADL); } +/// Builds an expression which might be an implicit member expression. +Sema::OwningExprResult +Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs) { + switch (ClassifyImplicitMemberAccess(*this, R)) { + case IMA_Instance: + return BuildImplicitMemberExpr(SS, R, TemplateArgs, true); + + case IMA_AnonymousMember: + assert(R.isSingleResult()); + return BuildAnonymousStructUnionMemberReference(R.getNameLoc(), + R.getAsSingle()); + + case IMA_Mixed: + case IMA_Mixed_Unrelated: + case IMA_Unresolved: + return BuildImplicitMemberExpr(SS, R, TemplateArgs, false); + + case IMA_Static: + case IMA_Mixed_StaticContext: + case IMA_Unresolved_StaticContext: + if (TemplateArgs) + return BuildTemplateIdExpr(SS, R, false, *TemplateArgs); + return BuildDeclarationNameExpr(SS, R, false); + + case IMA_Error_StaticContext: + case IMA_Error_Unrelated: + DiagnoseInstanceReference(*this, SS, R); + return ExprError(); + } + + llvm_unreachable("unexpected instance member access kind"); + return ExprError(); +} + /// BuildQualifiedDeclarationNameExpr - Build a C++ qualified /// declaration name, generally during template instantiation. /// There's a large number of things which don't need to be done along @@ -1315,7 +1386,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, // -- a declaration of a class member // Since using decls preserve this property, we check this on the // original decl. - if (IsClassMember(D)) + if (D->isCXXClassMember()) return false; // C++0x [basic.lookup.argdep]p3: @@ -1408,7 +1479,6 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, assert(D && "Cannot refer to a NULL declaration"); assert(!isa(D) && "Cannot refer unambiguously to a function template"); - DeclarationName Name = D->getDeclName(); if (CheckDeclInExpr(*this, Loc, D)) return ExprError(); @@ -1427,7 +1497,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, if (!VD) { Diag(Loc, diag::err_ref_non_value) << D << SS.getRange(); - Diag(D->getLocation(), diag::note_previous_declaration); + Diag(D->getLocation(), diag::note_declared_at); return ExprError(); } @@ -1515,11 +1585,17 @@ Sema::OwningExprResult Sema::ActOnCharacterConstant(const Token &Tok) { if (Literal.hadError()) return ExprError(); - QualType type = getLangOptions().CPlusPlus ? Context.CharTy : Context.IntTy; + QualType Ty; + if (!getLangOptions().CPlusPlus) + Ty = Context.IntTy; // 'x' and L'x' -> int in C. + else if (Literal.isWide()) + Ty = Context.WCharTy; // L'x' -> wchar_t in C++. + else + Ty = Context.CharTy; // 'x' -> char in C++ return Owned(new (Context) CharacterLiteral(Literal.getValue(), Literal.isWide(), - type, Tok.getLocation())); + Ty, Tok.getLocation())); } Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) { @@ -1558,9 +1634,31 @@ Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) { const llvm::fltSemantics &Format = Context.getFloatTypeSemantics(Ty); - // isExact will be set by GetFloatValue(). - bool isExact = false; - llvm::APFloat Val = Literal.GetFloatValue(Format, &isExact); + using llvm::APFloat; + APFloat Val(Format); + + APFloat::opStatus result = Literal.GetFloatValue(Val); + + // Overflow is always an error, but underflow is only an error if + // we underflowed to zero (APFloat reports denormals as underflow). + if ((result & APFloat::opOverflow) || + ((result & APFloat::opUnderflow) && Val.isZero())) { + unsigned diagnostic; + llvm::SmallVector buffer; + if (result & APFloat::opOverflow) { + diagnostic = diag::err_float_overflow; + APFloat::getLargest(Format).toString(buffer); + } else { + diagnostic = diag::err_float_underflow; + APFloat::getSmallest(Format).toString(buffer); + } + + Diag(Tok.getLocation(), diagnostic) + << Ty + << llvm::StringRef(buffer.data(), buffer.size()); + } + + bool isExact = (result == APFloat::opOK); Res = new (Context) FloatingLiteral(Val, isExact, Ty, Tok.getLocation()); } else if (!Literal.isIntegerLiteral()) { @@ -1698,9 +1796,8 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType, } if (RequireCompleteType(OpLoc, exprType, - isSizeof ? diag::err_sizeof_incomplete_type : - PDiag(diag::err_alignof_incomplete_type) - << ExprRange)) + PDiag(diag::err_sizeof_alignof_incomplete_type) + << int(!isSizeof) << ExprRange)) return true; // Reject sizeof(interface) and sizeof(interface) in 64-bit mode. @@ -2054,20 +2151,12 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc, } } - // If this is a halving swizzle, verify that the base type has an even - // number of elements. - if (HalvingSwizzle && (vecType->getNumElements() & 1U)) { - Diag(OpLoc, diag::err_ext_vector_component_requires_even) - << baseType << SourceRange(CompLoc); - return QualType(); - } - // The component accessor looks fine - now we need to compute the actual type. // The vector type is implied by the component accessor. For example, // vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc. // vec4.s0 is a float, vec4.s23 is a vec3, etc. // vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2. - unsigned CompSize = HalvingSwizzle ? vecType->getNumElements() / 2 + unsigned CompSize = HalvingSwizzle ? (vecType->getNumElements() + 1) / 2 : CompName->getLength(); if (HexSwizzle) CompSize--; @@ -2277,6 +2366,23 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, // The record definition is complete, now look up the member. SemaRef.LookupQualifiedName(R, DC); + if (!R.empty()) + return false; + + // We didn't find anything with the given name, so try to correct + // for typos. + DeclarationName Name = R.getLookupName(); + if (SemaRef.CorrectTypo(R, 0, &SS, DC) && + (isa(*R.begin()) || isa(*R.begin()))) { + SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest) + << Name << DC << R.getLookupName() << SS.getRange() + << CodeModificationHint::CreateReplacement(R.getNameLoc(), + R.getLookupName().getAsString()); + return false; + } else { + R.clear(); + } + return false; } @@ -2372,6 +2478,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, // result. if (R.isOverloadedResult() || R.isUnresolvableResult()) { bool Dependent = + BaseExprType->isDependentType() || R.isUnresolvableResult() || UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), TemplateArgs); @@ -3059,28 +3166,36 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, if (Result.isInvalid()) return ExprError(); - if (SetParamDefaultArgument(Param, move(Result), - /*FIXME:EqualLoc*/ - UninstExpr->getSourceRange().getBegin())) + // Check the expression as an initializer for the parameter. + InitializedEntity Entity + = InitializedEntity::InitializeParameter(Param); + InitializationKind Kind + = InitializationKind::CreateCopy(Param->getLocation(), + /*FIXME:EqualLoc*/UninstExpr->getSourceRange().getBegin()); + Expr *ResultE = Result.takeAs(); + + InitializationSequence InitSeq(*this, Entity, Kind, &ResultE, 1); + Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, (void**)&ResultE, 1)); + if (Result.isInvalid()) return ExprError(); + + // Build the default argument expression. + return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param, + Result.takeAs())); } - Expr *DefaultExpr = Param->getDefaultArg(); - // If the default expression creates temporaries, we need to // push them to the current stack of expression temporaries so they'll // be properly destroyed. - if (CXXExprWithTemporaries *E - = dyn_cast_or_null(DefaultExpr)) { - assert(!E->shouldDestroyTemporaries() && - "Can't destroy temporaries in a default argument expr!"); - for (unsigned I = 0, N = E->getNumTemporaries(); I != N; ++I) - ExprTemporaries.push_back(E->getTemporary(I)); - } + // FIXME: We should really be rebuilding the default argument with new + // bound temporaries; see the comment in PR5810. + for (unsigned i = 0, e = Param->getNumDefaultArgTemporaries(); i != e; ++i) + ExprTemporaries.push_back(Param->getDefaultArgTemporary(i)); } // We already type-checked the argument, so we know it works. - return Owned(CXXDefaultArgExpr::Create(Context, Param)); + return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param)); } /// ConvertArgumentsForCall - Converts the arguments specified in @@ -3169,12 +3284,22 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, << Arg->getSourceRange())) return true; - // Pass the argument. - if (PerformCopyInitialization(Arg, ProtoArgType, "passing")) - return true; + // Pass the argument + ParmVarDecl *Param = 0; + if (FDecl && i < FDecl->getNumParams()) + Param = FDecl->getParamDecl(i); + - if (!ProtoArgType->isReferenceType()) - Arg = MaybeBindToTemporary(Arg).takeAs(); + InitializedEntity Entity = + Param? InitializedEntity::InitializeParameter(Param) + : InitializedEntity::InitializeParameter(ProtoArgType); + OwningExprResult ArgE = PerformCopyInitialization(Entity, + SourceLocation(), + Owned(Arg)); + if (ArgE.isInvalid()) + return true; + + Arg = ArgE.takeAs(); } else { ParmVarDecl *Param = FDecl->getParamDecl(i); @@ -3200,64 +3325,6 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, return Invalid; } -/// \brief "Deconstruct" the function argument of a call expression to find -/// the underlying declaration (if any), the name of the called function, -/// whether argument-dependent lookup is available, whether it has explicit -/// template arguments, etc. -void Sema::DeconstructCallFunction(Expr *FnExpr, - llvm::SmallVectorImpl &Fns, - DeclarationName &Name, - NestedNameSpecifier *&Qualifier, - SourceRange &QualifierRange, - bool &ArgumentDependentLookup, - bool &Overloaded, - bool &HasExplicitTemplateArguments, - TemplateArgumentListInfo &ExplicitTemplateArgs) { - // Set defaults for all of the output parameters. - Name = DeclarationName(); - Qualifier = 0; - QualifierRange = SourceRange(); - ArgumentDependentLookup = false; - Overloaded = false; - HasExplicitTemplateArguments = false; - - // If we're directly calling a function, get the appropriate declaration. - // Also, in C++, keep track of whether we should perform argument-dependent - // lookup and whether there were any explicitly-specified template arguments. - while (true) { - if (ImplicitCastExpr *IcExpr = dyn_cast(FnExpr)) - FnExpr = IcExpr->getSubExpr(); - else if (ParenExpr *PExpr = dyn_cast(FnExpr)) { - FnExpr = PExpr->getSubExpr(); - } else if (isa(FnExpr) && - cast(FnExpr)->getOpcode() - == UnaryOperator::AddrOf) { - FnExpr = cast(FnExpr)->getSubExpr(); - } else if (DeclRefExpr *DRExpr = dyn_cast(FnExpr)) { - Fns.push_back(cast(DRExpr->getDecl())); - ArgumentDependentLookup = false; - if ((Qualifier = DRExpr->getQualifier())) - QualifierRange = DRExpr->getQualifierRange(); - break; - } else if (UnresolvedLookupExpr *UnresLookup - = dyn_cast(FnExpr)) { - Name = UnresLookup->getName(); - Fns.append(UnresLookup->decls_begin(), UnresLookup->decls_end()); - ArgumentDependentLookup = UnresLookup->requiresADL(); - Overloaded = UnresLookup->isOverloaded(); - if ((Qualifier = UnresLookup->getQualifier())) - QualifierRange = UnresLookup->getQualifierRange(); - if (UnresLookup->hasExplicitTemplateArgs()) { - HasExplicitTemplateArguments = true; - UnresLookup->copyTemplateArgumentsInto(ExplicitTemplateArgs); - } - break; - } else { - break; - } - } -} - /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. /// This provides the location of the left/right parens and a list of comma /// locations. @@ -3372,72 +3439,23 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, // If we're directly calling a function, get the appropriate declaration. // Also, in C++, keep track of whether we should perform argument-dependent // lookup and whether there were any explicitly-specified template arguments. - llvm::SmallVector Fns; - DeclarationName UnqualifiedName; - bool Overloaded; - bool ADL; - bool HasExplicitTemplateArgs = 0; - TemplateArgumentListInfo ExplicitTemplateArgs; - NestedNameSpecifier *Qualifier = 0; - SourceRange QualifierRange; - DeconstructCallFunction(Fn, Fns, UnqualifiedName, Qualifier, QualifierRange, - ADL, Overloaded, HasExplicitTemplateArgs, - ExplicitTemplateArgs); - - NamedDecl *NDecl; // the specific declaration we're calling, if applicable - FunctionDecl *FDecl; // same, if it's known to be a function - - if (Overloaded || ADL) { -#ifndef NDEBUG - if (ADL) { - // To do ADL, we must have found an unqualified name. - assert(UnqualifiedName && "found no unqualified name for ADL"); - - // We don't perform ADL for implicit declarations of builtins. - // Verify that this was correctly set up. - if (Fns.size() == 1 && (FDecl = dyn_cast(Fns[0])) && - FDecl->getBuiltinID() && FDecl->isImplicit()) - assert(0 && "performing ADL for builtin"); - - // We don't perform ADL in C. - assert(getLangOptions().CPlusPlus && "ADL enabled in C"); - } - - if (Overloaded) { - // To be overloaded, we must either have multiple functions or - // at least one function template (which is effectively an - // infinite set of functions). - assert((Fns.size() > 1 || - (Fns.size() == 1 && - isa(Fns[0]->getUnderlyingDecl()))) - && "unrecognized overload situation"); - } -#endif - - FDecl = ResolveOverloadedCallFn(Fn, Fns, UnqualifiedName, - (HasExplicitTemplateArgs ? &ExplicitTemplateArgs : 0), - LParenLoc, Args, NumArgs, CommaLocs, - RParenLoc, ADL); - if (!FDecl) - return ExprError(); - - Fn = FixOverloadedFunctionReference(Fn, FDecl); - NDecl = FDecl; - } else { - assert(Fns.size() <= 1 && "overloaded without Overloaded flag"); - if (Fns.empty()) - NDecl = 0; - else { - NDecl = Fns[0]; - } + Expr *NakedFn = Fn->IgnoreParens(); + if (isa(NakedFn)) { + UnresolvedLookupExpr *ULE = cast(NakedFn); + return BuildOverloadedCallExpr(Fn, ULE, LParenLoc, Args, NumArgs, + CommaLocs, RParenLoc); } + NamedDecl *NDecl = 0; + if (isa(NakedFn)) + NDecl = cast(NakedFn)->getDecl(); + return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc); } -/// BuildCallExpr - Build a call to a resolved expression, i.e. an -/// expression not of \p OverloadTy. The expression should +/// BuildResolvedCallExpr - Build a call to a resolved expression, +/// i.e. an expression not of \p OverloadTy. The expression should /// unary-convert to an expression of function-pointer or /// block-pointer type. /// @@ -3547,8 +3565,9 @@ Action::OwningExprResult Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty, SourceLocation RParenLoc, ExprArg InitExpr) { assert((Ty != 0) && "ActOnCompoundLiteral(): missing type"); - //FIXME: Preserve type source info. - QualType literalType = GetTypeFromParser(Ty); + + QualType literalType = GetTypeFromParser(Ty); + // FIXME: put back this assert when initializers are worked out. //assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression"); Expr *literalExpr = static_cast(InitExpr.get()); @@ -3564,16 +3583,29 @@ Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty, literalExpr->getSourceRange().getEnd()))) return ExprError(); - if (CheckInitializerTypes(literalExpr, literalType, LParenLoc, - DeclarationName(), /*FIXME:DirectInit=*/false)) + InitializedEntity Entity + = InitializedEntity::InitializeTemporary(literalType); + InitializationKind Kind + = InitializationKind::CreateCast(SourceRange(LParenLoc, RParenLoc), + /*IsCStyleCast=*/true); + InitializationSequence InitSeq(*this, Entity, Kind, &literalExpr, 1); + OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, (void**)&literalExpr, 1), + &literalType); + if (Result.isInvalid()) return ExprError(); + InitExpr.release(); + literalExpr = static_cast(Result.get()); bool isFileScope = getCurFunctionOrMethodDecl() == 0; if (isFileScope) { // 6.5.2.5p3 if (CheckForConstantInitializer(literalExpr, literalType)) return ExprError(); } - InitExpr.release(); + + Result.release(); + + // FIXME: Store the TInfo to preserve type information better. return Owned(new (Context) CompoundLiteralExpr(LParenLoc, literalType, literalExpr, isFileScope)); } @@ -3600,7 +3632,9 @@ static CastExpr::CastKind getScalarCastKind(ASTContext &Context, if (SrcTy->hasPointerRepresentation()) { if (DestTy->hasPointerRepresentation()) - return CastExpr::CK_BitCast; + return DestTy->isObjCObjectPointerType() ? + CastExpr::CK_AnyPointerToObjCPointerCast : + CastExpr::CK_BitCast; if (DestTy->isIntegerType()) return CastExpr::CK_PointerToIntegral; } @@ -4632,7 +4666,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { // expression is implicitly converted (C++ 4) to the // cv-unqualified type of the left operand. if (PerformImplicitConversion(rExpr, lhsType.getUnqualifiedType(), - "assigning")) + AA_Assigning)) return Incompatible; return Compatible; } @@ -5226,7 +5260,18 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (getLangOptions().CPlusPlus) { if (LCanPointeeTy == RCanPointeeTy) return ResultTy; - + if (!isRelational && + (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) { + // Valid unless comparison between non-null pointer and function pointer + // This is a gcc extension compatibility comparison. + if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType()) + && !LHSIsNull && !RHSIsNull) { + Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void) + << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + ImpCastExprToType(rex, lType, CastExpr::CK_BitCast); + return ResultTy; + } + } // C++ [expr.rel]p2: // [...] Pointer conversions (4.10) and qualification // conversions (4.4) are performed on pointer operands (or on @@ -5503,7 +5548,7 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] return InvalidOperands(Loc, lex, rex); if (PerformImplicitConversion(lex, Context.BoolTy, LHS, - "passing", /*IgnoreBaseAccess=*/false)) + AA_Passing, /*IgnoreBaseAccess=*/false)) return InvalidOperands(Loc, lex, rex); StandardConversionSequence RHS; @@ -5512,7 +5557,7 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] return InvalidOperands(Loc, lex, rex); if (PerformImplicitConversion(rex, Context.BoolTy, RHS, - "passing", /*IgnoreBaseAccess=*/false)) + AA_Passing, /*IgnoreBaseAccess=*/false)) return InvalidOperands(Loc, lex, rex); // C++ [expr.log.and]p2 @@ -5587,6 +5632,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { case Expr::MLV_NoSetterProperty: Diag = diag::error_nosetter_property_assignment; break; + case Expr::MLV_SubObjCPropertySetting: + Diag = diag::error_no_subobject_property_setting; + break; } SourceRange Assign; @@ -5651,7 +5699,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, } if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType, - RHS, "assigning")) + RHS, AA_Assigning)) return QualType(); // C99 6.5.16p3: The type of an assignment expression is the type of the @@ -5734,7 +5782,7 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc, << ResType << Op->getSourceRange(); } else { Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement) - << ResType << Op->getSourceRange(); + << ResType << int(isInc) << Op->getSourceRange(); return QualType(); } // At this point, we know we have a real, complex or pointer type. @@ -6478,28 +6526,12 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, // Get the decl corresponding to this. RecordDecl *RD = RC->getDecl(); if (CXXRecordDecl *CRD = dyn_cast(RD)) { - if (!CRD->isPOD() && !DidWarnAboutNonPOD) { - switch (ExprEvalContexts.back().Context ) { - case Unevaluated: - // The argument will never be evaluated, so don't complain. - break; - - case PotentiallyEvaluated: - ExprError(Diag(BuiltinLoc, diag::warn_offsetof_non_pod_type) - << SourceRange(CompPtr[0].LocStart, OC.LocEnd) - << Res->getType()); - DidWarnAboutNonPOD = true; - break; - - case PotentiallyPotentiallyEvaluated: - ExprEvalContexts.back().addDiagnostic(BuiltinLoc, - PDiag(diag::warn_offsetof_non_pod_type) - << SourceRange(CompPtr[0].LocStart, OC.LocEnd) - << Res->getType()); - DidWarnAboutNonPOD = true; - break; - } - } + if (!CRD->isPOD() && !DidWarnAboutNonPOD && + DiagRuntimeBehavior(BuiltinLoc, + PDiag(diag::warn_offsetof_non_pod_type) + << SourceRange(CompPtr[0].LocStart, OC.LocEnd) + << Res->getType())) + DidWarnAboutNonPOD = true; } LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName); @@ -6847,7 +6879,7 @@ MakeObjCStringLiteralCodeModificationHint(Sema& SemaRef, bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, SourceLocation Loc, QualType DstType, QualType SrcType, - Expr *SrcExpr, const char *Flavor) { + Expr *SrcExpr, AssignmentAction Action) { // Decode the result (notice that AST's are still created for extensions). bool isInvalid = false; unsigned DiagKind; @@ -6910,7 +6942,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, break; } - Diag(Loc, DiagKind) << DstType << SrcType << Flavor + Diag(Loc, DiagKind) << DstType << SrcType << Action << SrcExpr->getSourceRange() << Hint; return isInvalid; } @@ -7053,7 +7085,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { if (!Constructor->isUsed()) DefineImplicitDefaultConstructor(Loc, Constructor); } else if (Constructor->isImplicit() && - Constructor->isCopyConstructor(Context, TypeQuals)) { + Constructor->isCopyConstructor(TypeQuals)) { if (!Constructor->isUsed()) DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals); } @@ -7120,6 +7152,41 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { } } +/// \brief Emit a diagnostic that describes an effect on the run-time behavior +/// of the program being compiled. +/// +/// This routine emits the given diagnostic when the code currently being +/// type-checked is "potentially evaluated", meaning that there is a +/// possibility that the code will actually be executable. Code in sizeof() +/// expressions, code used only during overload resolution, etc., are not +/// potentially evaluated. This routine will suppress such diagnostics or, +/// in the absolutely nutty case of potentially potentially evaluated +/// expressions (C++ typeid), queue the diagnostic to potentially emit it +/// later. +/// +/// This routine should be used for all diagnostics that describe the run-time +/// behavior of a program, such as passing a non-POD value through an ellipsis. +/// Failure to do so will likely result in spurious diagnostics or failures +/// during overload resolution or within sizeof/alignof/typeof/typeid. +bool Sema::DiagRuntimeBehavior(SourceLocation Loc, + const PartialDiagnostic &PD) { + switch (ExprEvalContexts.back().Context ) { + case Unevaluated: + // The argument will never be evaluated, so don't complain. + break; + + case PotentiallyEvaluated: + Diag(Loc, PD); + return true; + + case PotentiallyPotentiallyEvaluated: + ExprEvalContexts.back().addDiagnostic(Loc, PD); + break; + } + + return false; +} + bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc, CallExpr *CE, FunctionDecl *FD) { if (ReturnType->isVoidType() || !ReturnType->isIncompleteType()) diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 6d991b6..5f723f9 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -31,9 +31,29 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, if (!StdNamespace) return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); - if (isType) + if (isType) { + // C++ [expr.typeid]p4: + // The top-level cv-qualifiers of the lvalue expression or the type-id + // that is the operand of typeid are always ignored. // FIXME: Preserve type source info. - TyOrExpr = GetTypeFromParser(TyOrExpr).getAsOpaquePtr(); + // FIXME: Preserve the type before we stripped the cv-qualifiers? + QualType T = GetTypeFromParser(TyOrExpr); + if (T.isNull()) + return ExprError(); + + // C++ [expr.typeid]p4: + // If the type of the type-id is a class type or a reference to a class + // type, the class shall be completely-defined. + QualType CheckT = T; + if (const ReferenceType *RefType = CheckT->getAs()) + CheckT = RefType->getPointeeType(); + + if (CheckT->getAs() && + RequireCompleteType(OpLoc, CheckT, diag::err_incomplete_typeid)) + return ExprError(); + + TyOrExpr = T.getUnqualifiedType().getAsOpaquePtr(); + } IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info"); LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName); @@ -45,21 +65,36 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, QualType TypeInfoType = Context.getTypeDeclType(TypeInfoRecordDecl); if (!isType) { - // C++0x [expr.typeid]p3: - // When typeid is applied to an expression other than an lvalue of a - // polymorphic class type [...] [the] expression is an unevaluated - // operand. - - // FIXME: if the type of the expression is a class type, the class - // shall be completely defined. bool isUnevaluatedOperand = true; Expr *E = static_cast(TyOrExpr); - if (E && !E->isTypeDependent() && E->isLvalue(Context) == Expr::LV_Valid) { + if (E && !E->isTypeDependent()) { QualType T = E->getType(); if (const RecordType *RecordT = T->getAs()) { CXXRecordDecl *RecordD = cast(RecordT->getDecl()); - if (RecordD->isPolymorphic()) + // C++ [expr.typeid]p3: + // When typeid is applied to an expression other than an lvalue of a + // polymorphic class type [...] [the] expression is an unevaluated + // operand. [...] + if (RecordD->isPolymorphic() && E->isLvalue(Context) == Expr::LV_Valid) isUnevaluatedOperand = false; + else { + // C++ [expr.typeid]p3: + // [...] If the type of the expression is a class type, the class + // shall be completely-defined. + if (RequireCompleteType(OpLoc, T, diag::err_incomplete_typeid)) + return ExprError(); + } + } + + // C++ [expr.typeid]p4: + // [...] If the type of the type-id is a reference to a possibly + // cv-qualified type, the result of the typeid expression refers to a + // std::type_info object representing the cv-unqualified referenced + // type. + if (T.hasQualifiers()) { + ImpCastExprToType(E, T.getUnqualifiedType(), CastExpr::CK_NoOp, + E->isLvalue(Context)); + TyOrExpr = E; } } @@ -102,8 +137,15 @@ Sema::ActOnCXXThrow(SourceLocation OpLoc, ExprArg E) { /// CheckCXXThrowOperand - Validate the operand of a throw. bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { // C++ [except.throw]p3: - // [...] adjusting the type from "array of T" or "function returning T" - // to "pointer to T" or "pointer to function returning T", [...] + // A throw-expression initializes a temporary object, called the exception + // object, the type of which is determined by removing any top-level + // cv-qualifiers from the static type of the operand of throw and adjusting + // the type from "array of T" or "function returning T" to "pointer to T" + // or "pointer to function returning T", [...] + if (E->getType().hasQualifiers()) + ImpCastExprToType(E, E->getType().getUnqualifiedType(), CastExpr::CK_NoOp, + E->isLvalue(Context) == Expr::LV_Valid); + DefaultFunctionArrayConversion(E); // If the type of the exception would be an incomplete type or a pointer @@ -425,74 +467,61 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, bool Init = ConstructorLParen.isValid(); // --- Choosing a constructor --- - // C++ 5.3.4p15 - // 1) If T is a POD and there's no initializer (ConstructorLParen is invalid) - // the object is not initialized. If the object, or any part of it, is - // const-qualified, it's an error. - // 2) If T is a POD and there's an empty initializer, the object is value- - // initialized. - // 3) If T is a POD and there's one initializer argument, the object is copy- - // constructed. - // 4) If T is a POD and there's more initializer arguments, it's an error. - // 5) If T is not a POD, the initializer arguments are used as constructor - // arguments. - // - // Or by the C++0x formulation: - // 1) If there's no initializer, the object is default-initialized according - // to C++0x rules. - // 2) Otherwise, the object is direct-initialized. CXXConstructorDecl *Constructor = 0; Expr **ConsArgs = (Expr**)ConstructorArgs.get(); - const RecordType *RT; unsigned NumConsArgs = ConstructorArgs.size(); ASTOwningVector<&ActionBase::DeleteExpr> ConvertedConstructorArgs(*this); - if (AllocType->isDependentType() || - Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) { - // Skip all the checks. - } else if ((RT = AllocType->getAs()) && - !AllocType->isAggregateType()) { - InitializationKind InitKind = InitializationKind::CreateDefault(TypeLoc); - if (NumConsArgs > 0) - InitKind = InitializationKind::CreateDirect(TypeLoc, - PlacementLParen, - PlacementRParen); - Constructor = PerformInitializationByConstructor( - AllocType, move(ConstructorArgs), - TypeLoc, - SourceRange(TypeLoc, ConstructorRParen), - RT->getDecl()->getDeclName(), - InitKind, - ConvertedConstructorArgs); - if (!Constructor) + if (!AllocType->isDependentType() && + !Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) { + // C++0x [expr.new]p15: + // A new-expression that creates an object of type T initializes that + // object as follows: + InitializationKind Kind + // - If the new-initializer is omitted, the object is default- + // initialized (8.5); if no initialization is performed, + // the object has indeterminate value + = !Init? InitializationKind::CreateDefault(TypeLoc) + // - Otherwise, the new-initializer is interpreted according to the + // initialization rules of 8.5 for direct-initialization. + : InitializationKind::CreateDirect(TypeLoc, + ConstructorLParen, + ConstructorRParen); + + InitializedEntity Entity + = InitializedEntity::InitializeNew(StartLoc, AllocType); + InitializationSequence InitSeq(*this, Entity, Kind, ConsArgs, NumConsArgs); + OwningExprResult FullInit = InitSeq.Perform(*this, Entity, Kind, + move(ConstructorArgs)); + if (FullInit.isInvalid()) return ExprError(); - - // Take the converted constructor arguments and use them for the new - // expression. - NumConsArgs = ConvertedConstructorArgs.size(); - ConsArgs = (Expr **)ConvertedConstructorArgs.take(); - } else { - if (!Init) { - // FIXME: Check that no subpart is const. - if (AllocType.isConstQualified()) - return ExprError(Diag(StartLoc, diag::err_new_uninitialized_const) - << TypeRange); - } else if (NumConsArgs == 0) { - // Object is value-initialized. Do nothing. - } else if (NumConsArgs == 1) { - // Object is direct-initialized. - // FIXME: What DeclarationName do we pass in here? - if (CheckInitializerTypes(ConsArgs[0], AllocType, StartLoc, - DeclarationName() /*AllocType.getAsString()*/, - /*DirectInit=*/true)) - return ExprError(); + + // FullInit is our initializer; walk through it to determine if it's a + // constructor call, which CXXNewExpr handles directly. + if (Expr *FullInitExpr = (Expr *)FullInit.get()) { + if (CXXBindTemporaryExpr *Binder + = dyn_cast(FullInitExpr)) + FullInitExpr = Binder->getSubExpr(); + if (CXXConstructExpr *Construct + = dyn_cast(FullInitExpr)) { + Constructor = Construct->getConstructor(); + for (CXXConstructExpr::arg_iterator A = Construct->arg_begin(), + AEnd = Construct->arg_end(); + A != AEnd; ++A) + ConvertedConstructorArgs.push_back(A->Retain()); + } else { + // Take the converted initializer. + ConvertedConstructorArgs.push_back(FullInit.release()); + } } else { - return ExprError(Diag(StartLoc, - diag::err_builtin_direct_init_more_than_one_arg) - << SourceRange(ConstructorLParen, ConstructorRParen)); + // No initialization required. } + + // Take the converted arguments and use them for the new expression. + NumConsArgs = ConvertedConstructorArgs.size(); + ConsArgs = (Expr **)ConvertedConstructorArgs.take(); } - + // FIXME: Also check that the destructor is accessible. (C++ 5.3.4p16) PlacementArgs.release(); @@ -631,10 +660,9 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, // Whatch out for variadic allocator function. unsigned NumArgsInFnDecl = FnDecl->getNumParams(); for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) { - // FIXME: Passing word to diagnostic. if (PerformCopyInitialization(Args[i], FnDecl->getParamDecl(i)->getType(), - "passing")) + AA_Passing)) return true; } Operator = FnDecl; @@ -720,13 +748,14 @@ void Sema::DeclareGlobalNewDelete() { QualType VoidPtr = Context.getPointerType(Context.VoidTy); QualType SizeT = Context.getSizeType(); + bool AssumeSaneOperatorNew = getLangOptions().AssumeSaneOperatorNew; DeclareGlobalAllocationFunction( Context.DeclarationNames.getCXXOperatorName(OO_New), - VoidPtr, SizeT); + VoidPtr, SizeT, AssumeSaneOperatorNew); DeclareGlobalAllocationFunction( Context.DeclarationNames.getCXXOperatorName(OO_Array_New), - VoidPtr, SizeT); + VoidPtr, SizeT, AssumeSaneOperatorNew); DeclareGlobalAllocationFunction( Context.DeclarationNames.getCXXOperatorName(OO_Delete), Context.VoidTy, VoidPtr); @@ -738,7 +767,8 @@ void Sema::DeclareGlobalNewDelete() { /// DeclareGlobalAllocationFunction - Declares a single implicit global /// allocation function if it doesn't already exist. void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, - QualType Return, QualType Argument) { + QualType Return, QualType Argument, + bool AddMallocAttr) { DeclContext *GlobalCtx = Context.getTranslationUnitDecl(); // Check if this function is already declared. @@ -749,7 +779,8 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, // FIXME: Do we need to check for default arguments here? FunctionDecl *Func = cast(*Alloc); if (Func->getNumParams() == 1 && - Context.getCanonicalType(Func->getParamDecl(0)->getType())==Argument) + Context.getCanonicalType( + Func->getParamDecl(0)->getType().getUnqualifiedType()) == Argument) return; } } @@ -771,6 +802,10 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), Name, FnType, /*TInfo=*/0, FunctionDecl::None, false, true); Alloc->setImplicit(); + + if (AddMallocAttr) + Alloc->addAttr(::new (Context) MallocAttr()); + ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(), 0, Argument, /*TInfo=*/0, VarDecl::None, 0); @@ -876,7 +911,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, Operand.release(); if (!PerformImplicitConversion(Ex, ObjectPtrConversions.front()->getConversionType(), - "converting")) { + AA_Converting)) { Operand = Owned(Ex); Type = Ex->getType(); } @@ -1027,16 +1062,16 @@ Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) { /// resolution works differently in that case. bool Sema::PerformImplicitConversion(Expr *&From, QualType ToType, - const char *Flavor, bool AllowExplicit, + AssignmentAction Action, bool AllowExplicit, bool Elidable) { ImplicitConversionSequence ICS; - return PerformImplicitConversion(From, ToType, Flavor, AllowExplicit, + return PerformImplicitConversion(From, ToType, Action, AllowExplicit, Elidable, ICS); } bool Sema::PerformImplicitConversion(Expr *&From, QualType ToType, - const char *Flavor, bool AllowExplicit, + AssignmentAction Action, bool AllowExplicit, bool Elidable, ImplicitConversionSequence& ICS) { ICS.ConversionKind = ImplicitConversionSequence::BadConversion; @@ -1054,7 +1089,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, /*ForceRValue=*/false, /*InOverloadResolution=*/false); } - return PerformImplicitConversion(From, ToType, ICS, Flavor); + return PerformImplicitConversion(From, ToType, ICS, Action); } /// BuildCXXDerivedToBaseExpr - This routine generates the suitable AST @@ -1062,8 +1097,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, /// necessary information is passed in ICS. bool Sema::BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind, - const ImplicitConversionSequence& ICS, - const char *Flavor) { + const ImplicitConversionSequence& ICS) { QualType BaseType = QualType::getFromOpaquePtr(ICS.UserDefined.After.ToTypePtr); // Must do additional defined to base conversion. @@ -1095,15 +1129,15 @@ Sema::BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind, /// expression From to the type ToType using the pre-computed implicit /// conversion sequence ICS. Returns true if there was an error, false /// otherwise. The expression From is replaced with the converted -/// expression. Flavor is the kind of conversion we're performing, +/// expression. Action is the kind of conversion we're performing, /// used in the error message. bool Sema::PerformImplicitConversion(Expr *&From, QualType ToType, const ImplicitConversionSequence &ICS, - const char* Flavor, bool IgnoreBaseAccess) { + AssignmentAction Action, bool IgnoreBaseAccess) { switch (ICS.ConversionKind) { case ImplicitConversionSequence::StandardConversion: - if (PerformImplicitConversion(From, ToType, ICS.Standard, Flavor, + if (PerformImplicitConversion(From, ToType, ICS.Standard, Action, IgnoreBaseAccess)) return true; break; @@ -1136,7 +1170,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, // Whatch out for elipsis conversion. if (!ICS.UserDefined.EllipsisConversion) { if (PerformImplicitConversion(From, BeforeToType, - ICS.UserDefined.Before, "converting", + ICS.UserDefined.Before, AA_Converting, IgnoreBaseAccess)) return true; } @@ -1156,7 +1190,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, // there's some nasty stuff involving MaybeBindToTemporary going on here. if (ICS.UserDefined.After.Second == ICK_Derived_To_Base && ICS.UserDefined.After.CopyConstructor) { - return BuildCXXDerivedToBaseExpr(From, CastKind, ICS, Flavor); + return BuildCXXDerivedToBaseExpr(From, CastKind, ICS); } if (ICS.UserDefined.After.CopyConstructor) { @@ -1167,7 +1201,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, } return PerformImplicitConversion(From, ToType, ICS.UserDefined.After, - "converting", IgnoreBaseAccess); + AA_Converting, IgnoreBaseAccess); } case ImplicitConversionSequence::EllipsisConversion: @@ -1191,7 +1225,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, bool Sema::PerformImplicitConversion(Expr *&From, QualType ToType, const StandardConversionSequence& SCS, - const char *Flavor, bool IgnoreBaseAccess) { + AssignmentAction Action, bool IgnoreBaseAccess) { // Overall FIXME: we are recomputing too many types here and doing far too // much extra work. What this means is that we need to keep track of more // information that is computed when we try the implicit conversion initially, @@ -1323,7 +1357,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, // Diagnose incompatible Objective-C conversions Diag(From->getSourceRange().getBegin(), diag::ext_typecheck_convert_incompatible_pointer) - << From->getType() << ToType << Flavor + << From->getType() << ToType << Action << From->getSourceRange(); } @@ -1595,9 +1629,9 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS, case OR_Success: // We found a match. Perform the conversions on the arguments and move on. if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], "converting") || + Best->Conversions[0], Sema::AA_Converting) || Self.PerformImplicitConversion(RHS, Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], "converting")) + Best->Conversions[1], Sema::AA_Converting)) break; return false; @@ -1655,7 +1689,7 @@ static bool ConvertForConditional(Sema &Self, Expr *&E, /*AllowExplicit=*/false, /*ForceRValue=*/false); } - if (Self.PerformImplicitConversion(E, TargetType(ICS), ICS, "converting")) + if (Self.PerformImplicitConversion(E, TargetType(ICS), ICS, Sema::AA_Converting)) return true; return false; } @@ -1879,9 +1913,9 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, LPointee = Context.getQualifiedType(LPointee, MergedQuals); QualType Common = Context.getMemberPointerType(LPointee, MoreDerived.getTypePtr()); - if (PerformImplicitConversion(LHS, Common, "converting")) + if (PerformImplicitConversion(LHS, Common, Sema::AA_Converting)) return QualType(); - if (PerformImplicitConversion(RHS, Common, "converting")) + if (PerformImplicitConversion(RHS, Common, Sema::AA_Converting)) return QualType(); return Common; } @@ -2046,13 +2080,13 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) { && E2ToC2.ConversionKind != ImplicitConversionSequence::BadConversion; if (ToC1Viable && !ToC2Viable) { - if (!PerformImplicitConversion(E1, Composite1, E1ToC1, "converting") && - !PerformImplicitConversion(E2, Composite1, E2ToC1, "converting")) + if (!PerformImplicitConversion(E1, Composite1, E1ToC1, Sema::AA_Converting) && + !PerformImplicitConversion(E2, Composite1, E2ToC1, Sema::AA_Converting)) return Composite1; } if (ToC2Viable && !ToC1Viable) { - if (!PerformImplicitConversion(E1, Composite2, E1ToC2, "converting") && - !PerformImplicitConversion(E2, Composite2, E2ToC2, "converting")) + if (!PerformImplicitConversion(E1, Composite2, E1ToC2, Sema::AA_Converting) && + !PerformImplicitConversion(E2, Composite2, E2ToC2, Sema::AA_Converting)) return Composite2; } return QualType(); @@ -2062,6 +2096,8 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) { if (!Context.getLangOptions().CPlusPlus) return Owned(E); + assert(!isa(E) && "Double-bound temporary?"); + const RecordType *RT = E->getType()->getAs(); if (!RT) return Owned(E); @@ -2089,8 +2125,7 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) { return Owned(CXXBindTemporaryExpr::Create(Context, Temp, E)); } -Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr, - bool ShouldDestroyTemps) { +Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr) { assert(SubExpr && "sub expression can't be null!"); unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries; @@ -2100,8 +2135,31 @@ Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr, Expr *E = CXXExprWithTemporaries::Create(Context, SubExpr, &ExprTemporaries[FirstTemporary], - ExprTemporaries.size() - FirstTemporary, - ShouldDestroyTemps); + ExprTemporaries.size() - FirstTemporary); + ExprTemporaries.erase(ExprTemporaries.begin() + FirstTemporary, + ExprTemporaries.end()); + + return E; +} + +Sema::OwningExprResult +Sema::MaybeCreateCXXExprWithTemporaries(OwningExprResult SubExpr) { + if (SubExpr.isInvalid()) + return ExprError(); + + return Owned(MaybeCreateCXXExprWithTemporaries(SubExpr.takeAs())); +} + +FullExpr Sema::CreateFullExpr(Expr *SubExpr) { + unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries; + assert(ExprTemporaries.size() >= FirstTemporary); + + unsigned NumTemporaries = ExprTemporaries.size() - FirstTemporary; + CXXTemporary **Temporaries = + NumTemporaries == 0 ? 0 : &ExprTemporaries[FirstTemporary]; + + FullExpr E = FullExpr::Create(Context, SubExpr, Temporaries, NumTemporaries); + ExprTemporaries.erase(ExprTemporaries.begin() + FirstTemporary, ExprTemporaries.end()); @@ -2243,9 +2301,7 @@ Sema::OwningExprResult Sema::BuildCXXCastArgument(SourceLocation CastLoc, Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) { Expr *FullExpr = Arg.takeAs(); if (FullExpr) - FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr, - /*ShouldDestroyTemps=*/true); - + FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr); return Owned(FullExpr); } diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index b78c10b..2e31e47 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -205,7 +205,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, IsError |= DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType, - argExpr, "sending"); + argExpr, AA_Sending); } // Promote additional arguments to variadic methods. diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 4518465..3ef5156 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -16,11 +16,13 @@ //===----------------------------------------------------------------------===// #include "SemaInit.h" +#include "Lookup.h" #include "Sema.h" #include "clang/Parse/Designator.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/TypeLoc.h" #include "llvm/Support/ErrorHandling.h" #include using namespace clang; @@ -73,7 +75,7 @@ static bool CheckSingleInitializer(Expr *&Init, QualType DeclType, if (S.getLangOptions().CPlusPlus) { // FIXME: I dislike this error message. A lot. if (S.PerformImplicitConversion(Init, DeclType, - "initializing", DirectInit)) { + Sema::AA_Initializing, DirectInit)) { ImplicitConversionSequence ICS; OverloadCandidateSet CandidateSet; if (S.IsUserDefinedConversion(Init, DeclType, ICS.UserDefined, @@ -81,7 +83,7 @@ static bool CheckSingleInitializer(Expr *&Init, QualType DeclType, true, false, false) != OR_Ambiguous) return S.Diag(Init->getSourceRange().getBegin(), diag::err_typecheck_convert_incompatible) - << DeclType << Init->getType() << "initializing" + << DeclType << Init->getType() << Sema::AA_Initializing << Init->getSourceRange(); S.Diag(Init->getSourceRange().getBegin(), diag::err_typecheck_convert_ambiguous) @@ -95,7 +97,7 @@ static bool CheckSingleInitializer(Expr *&Init, QualType DeclType, Sema::AssignConvertType ConvTy = S.CheckSingleAssignmentConstraints(DeclType, Init); return S.DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType, - InitType, Init, "initializing"); + InitType, Init, Sema::AA_Initializing); } static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) { @@ -134,172 +136,6 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) { Str->setType(DeclT); } -bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType, - SourceLocation InitLoc, - DeclarationName InitEntity, bool DirectInit) { - if (DeclType->isDependentType() || - Init->isTypeDependent() || Init->isValueDependent()) { - // We have either a dependent type or a type- or value-dependent - // initializer, so we don't perform any additional checking at - // this point. - - // If the declaration is a non-dependent, incomplete array type - // that has an initializer, then its type will be completed once - // the initializer is instantiated. - if (!DeclType->isDependentType()) { - if (const IncompleteArrayType *ArrayT - = Context.getAsIncompleteArrayType(DeclType)) { - if (InitListExpr *ILE = dyn_cast(Init)) { - if (!ILE->isTypeDependent()) { - // Compute the constant array type from the length of the - // initializer list. - // FIXME: This will be wrong if there are designated - // initializations. Good thing they don't exist in C++! - llvm::APInt NumElements(Context.getTypeSize(Context.getSizeType()), - ILE->getNumInits()); - llvm::APInt Zero(Context.getTypeSize(Context.getSizeType()), 0); - if (NumElements == Zero) { - // Sizing an array implicitly to zero is not allowed by ISO C, - // but is supported by GNU. - Diag(ILE->getLocStart(), diag::ext_typecheck_zero_array_size); - } - - DeclType = Context.getConstantArrayType(ArrayT->getElementType(), - NumElements, - ArrayT->getSizeModifier(), - ArrayT->getIndexTypeCVRQualifiers()); - return false; - } - } - - // Make the array type-dependent by making it dependently-sized. - DeclType = Context.getDependentSizedArrayType(ArrayT->getElementType(), - /*NumElts=*/0, - ArrayT->getSizeModifier(), - ArrayT->getIndexTypeCVRQualifiers(), - SourceRange()); - } - } - - return false; - } - - // C++ [dcl.init.ref]p1: - // A variable declared to be a T& or T&&, that is "reference to type T" - // (8.3.2), shall be initialized by an object, or function, of - // type T or by an object that can be converted into a T. - if (DeclType->isReferenceType()) - return CheckReferenceInit(Init, DeclType, InitLoc, - /*SuppressUserConversions=*/false, - /*AllowExplicit=*/DirectInit, - /*ForceRValue=*/false); - - // C99 6.7.8p3: The type of the entity to be initialized shall be an array - // of unknown size ("[]") or an object type that is not a variable array type. - if (const VariableArrayType *VAT = Context.getAsVariableArrayType(DeclType)) - return Diag(InitLoc, diag::err_variable_object_no_init) - << VAT->getSizeExpr()->getSourceRange(); - - InitListExpr *InitList = dyn_cast(Init); - if (!InitList) { - // FIXME: Handle wide strings - if (Expr *Str = IsStringInit(Init, DeclType, Context)) { - CheckStringInit(Str, DeclType, *this); - return false; - } - - // C++ [dcl.init]p14: - // -- If the destination type is a (possibly cv-qualified) class - // type: - if (getLangOptions().CPlusPlus && DeclType->isRecordType()) { - QualType DeclTypeC = Context.getCanonicalType(DeclType); - QualType InitTypeC = Context.getCanonicalType(Init->getType()); - - // -- If the initialization is direct-initialization, or if it is - // copy-initialization where the cv-unqualified version of the - // source type is the same class as, or a derived class of, the - // class of the destination, constructors are considered. - if ((DeclTypeC.getLocalUnqualifiedType() - == InitTypeC.getLocalUnqualifiedType()) || - IsDerivedFrom(InitTypeC, DeclTypeC)) { - const CXXRecordDecl *RD = - cast(DeclType->getAs()->getDecl()); - - // No need to make a CXXConstructExpr if both the ctor and dtor are - // trivial. - if (RD->hasTrivialConstructor() && RD->hasTrivialDestructor()) - return false; - - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); - - // FIXME: Poor location information - InitializationKind InitKind - = InitializationKind::CreateCopy(Init->getLocStart(), - SourceLocation()); - if (DirectInit) - InitKind = InitializationKind::CreateDirect(Init->getLocStart(), - SourceLocation(), - SourceLocation()); - CXXConstructorDecl *Constructor - = PerformInitializationByConstructor(DeclType, - MultiExprArg(*this, - (void **)&Init, 1), - InitLoc, Init->getSourceRange(), - InitEntity, InitKind, - ConstructorArgs); - if (!Constructor) - return true; - - OwningExprResult InitResult = - BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), - DeclType, Constructor, - move_arg(ConstructorArgs)); - if (InitResult.isInvalid()) - return true; - - Init = InitResult.takeAs(); - return false; - } - - // -- Otherwise (i.e., for the remaining copy-initialization - // cases), user-defined conversion sequences that can - // convert from the source type to the destination type or - // (when a conversion function is used) to a derived class - // thereof are enumerated as described in 13.3.1.4, and the - // best one is chosen through overload resolution - // (13.3). If the conversion cannot be done or is - // ambiguous, the initialization is ill-formed. The - // function selected is called with the initializer - // expression as its argument; if the function is a - // constructor, the call initializes a temporary of the - // destination type. - // FIXME: We're pretending to do copy elision here; return to this when we - // have ASTs for such things. - if (!PerformImplicitConversion(Init, DeclType, "initializing")) - return false; - - if (InitEntity) - return Diag(InitLoc, diag::err_cannot_initialize_decl) - << InitEntity << (int)(Init->isLvalue(Context) == Expr::LV_Valid) - << Init->getType() << Init->getSourceRange(); - return Diag(InitLoc, diag::err_cannot_initialize_decl_noname) - << DeclType << (int)(Init->isLvalue(Context) == Expr::LV_Valid) - << Init->getType() << Init->getSourceRange(); - } - - // C99 6.7.8p16. - if (DeclType->isArrayType()) - return Diag(Init->getLocStart(), diag::err_array_init_list_required) - << Init->getSourceRange(); - - return CheckSingleInitializer(Init, DeclType, DirectInit, *this); - } - - bool hadError = CheckInitList(InitList, DeclType); - Init = InitList; - return hadError; -} - //===----------------------------------------------------------------------===// // Semantic checking for initializer lists. //===----------------------------------------------------------------------===// @@ -399,9 +235,14 @@ class InitListChecker { int numArrayElements(QualType DeclType); int numStructUnionElements(QualType DeclType); - void FillInValueInitializations(InitListExpr *ILE); + void FillInValueInitForField(unsigned Init, FieldDecl *Field, + const InitializedEntity &ParentEntity, + InitListExpr *ILE, bool &RequiresSecondPass); + void FillInValueInitializations(const InitializedEntity &Entity, + InitListExpr *ILE, bool &RequiresSecondPass); public: - InitListChecker(Sema &S, InitListExpr *IL, QualType &T); + InitListChecker(Sema &S, const InitializedEntity &Entity, + InitListExpr *IL, QualType &T); bool HadError() { return hadError; } // @brief Retrieves the fully-structured initializer list used for @@ -410,10 +251,75 @@ public: }; } // end anonymous namespace +void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field, + const InitializedEntity &ParentEntity, + InitListExpr *ILE, + bool &RequiresSecondPass) { + SourceLocation Loc = ILE->getSourceRange().getBegin(); + unsigned NumInits = ILE->getNumInits(); + InitializedEntity MemberEntity + = InitializedEntity::InitializeMember(Field, &ParentEntity); + if (Init >= NumInits || !ILE->getInit(Init)) { + // FIXME: We probably don't need to handle references + // specially here, since value-initialization of references is + // handled in InitializationSequence. + if (Field->getType()->isReferenceType()) { + // C++ [dcl.init.aggr]p9: + // If an incomplete or empty initializer-list leaves a + // member of reference type uninitialized, the program is + // ill-formed. + SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized) + << Field->getType() + << ILE->getSyntacticForm()->getSourceRange(); + SemaRef.Diag(Field->getLocation(), + diag::note_uninit_reference_member); + hadError = true; + return; + } + + InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, + true); + InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, 0, 0); + if (!InitSeq) { + InitSeq.Diagnose(SemaRef, MemberEntity, Kind, 0, 0); + hadError = true; + return; + } + + Sema::OwningExprResult MemberInit + = InitSeq.Perform(SemaRef, MemberEntity, Kind, + Sema::MultiExprArg(SemaRef, 0, 0)); + if (MemberInit.isInvalid()) { + hadError = true; + return; + } + + if (hadError) { + // Do nothing + } else if (Init < NumInits) { + ILE->setInit(Init, MemberInit.takeAs()); + } else if (InitSeq.getKind() + == InitializationSequence::ConstructorInitialization) { + // Value-initialization requires a constructor call, so + // extend the initializer list to include the constructor + // call and make a note that we'll need to take another pass + // through the initializer list. + ILE->updateInit(Init, MemberInit.takeAs()); + RequiresSecondPass = true; + } + } else if (InitListExpr *InnerILE + = dyn_cast(ILE->getInit(Init))) + FillInValueInitializations(MemberEntity, InnerILE, + RequiresSecondPass); +} + /// Recursively replaces NULL values within the given initializer list /// with expressions that perform value-initialization of the /// appropriate type. -void InitListChecker::FillInValueInitializations(InitListExpr *ILE) { +void +InitListChecker::FillInValueInitializations(const InitializedEntity &Entity, + InitListExpr *ILE, + bool &RequiresSecondPass) { assert((ILE->getType() != SemaRef.Context.VoidTy) && "Should not have void type"); SourceLocation Loc = ILE->getSourceRange().getBegin(); @@ -421,46 +327,32 @@ void InitListChecker::FillInValueInitializations(InitListExpr *ILE) { Loc = ILE->getSyntacticForm()->getSourceRange().getBegin(); if (const RecordType *RType = ILE->getType()->getAs()) { - unsigned Init = 0, NumInits = ILE->getNumInits(); - for (RecordDecl::field_iterator - Field = RType->getDecl()->field_begin(), - FieldEnd = RType->getDecl()->field_end(); - Field != FieldEnd; ++Field) { - if (Field->isUnnamedBitfield()) - continue; - - if (Init >= NumInits || !ILE->getInit(Init)) { - if (Field->getType()->isReferenceType()) { - // C++ [dcl.init.aggr]p9: - // If an incomplete or empty initializer-list leaves a - // member of reference type uninitialized, the program is - // ill-formed. - SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized) - << Field->getType() - << ILE->getSyntacticForm()->getSourceRange(); - SemaRef.Diag(Field->getLocation(), - diag::note_uninit_reference_member); - hadError = true; + if (RType->getDecl()->isUnion() && + ILE->getInitializedFieldInUnion()) + FillInValueInitForField(0, ILE->getInitializedFieldInUnion(), + Entity, ILE, RequiresSecondPass); + else { + unsigned Init = 0; + for (RecordDecl::field_iterator + Field = RType->getDecl()->field_begin(), + FieldEnd = RType->getDecl()->field_end(); + Field != FieldEnd; ++Field) { + if (Field->isUnnamedBitfield()) + continue; + + if (hadError) return; - } else if (SemaRef.CheckValueInitialization(Field->getType(), Loc)) { - hadError = true; + + FillInValueInitForField(Init, *Field, Entity, ILE, RequiresSecondPass); + if (hadError) return; - } - // FIXME: If value-initialization involves calling a constructor, should - // we make that call explicit in the representation (even when it means - // extending the initializer list)? - if (Init < NumInits && !hadError) - ILE->setInit(Init, - new (SemaRef.Context) ImplicitValueInitExpr(Field->getType())); - } else if (InitListExpr *InnerILE - = dyn_cast(ILE->getInit(Init))) - FillInValueInitializations(InnerILE); - ++Init; + ++Init; - // Only look at the first initialization of a union. - if (RType->getDecl()->isUnion()) - break; + // Only look at the first initialization of a union. + if (RType->getDecl()->isUnion()) + break; + } } return; @@ -468,39 +360,71 @@ void InitListChecker::FillInValueInitializations(InitListExpr *ILE) { QualType ElementType; + InitializedEntity ElementEntity = Entity; unsigned NumInits = ILE->getNumInits(); unsigned NumElements = NumInits; if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) { ElementType = AType->getElementType(); if (const ConstantArrayType *CAType = dyn_cast(AType)) NumElements = CAType->getSize().getZExtValue(); + ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, + 0, Entity); } else if (const VectorType *VType = ILE->getType()->getAs()) { ElementType = VType->getElementType(); NumElements = VType->getNumElements(); + ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, + 0, Entity); } else ElementType = ILE->getType(); + for (unsigned Init = 0; Init != NumElements; ++Init) { + if (hadError) + return; + + if (ElementEntity.getKind() == InitializedEntity::EK_ArrayOrVectorElement) + ElementEntity.setElementIndex(Init); + if (Init >= NumInits || !ILE->getInit(Init)) { - if (SemaRef.CheckValueInitialization(ElementType, Loc)) { + InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, + true); + InitializationSequence InitSeq(SemaRef, ElementEntity, Kind, 0, 0); + if (!InitSeq) { + InitSeq.Diagnose(SemaRef, ElementEntity, Kind, 0, 0); hadError = true; return; } - // FIXME: If value-initialization involves calling a constructor, should - // we make that call explicit in the representation (even when it means - // extending the initializer list)? - if (Init < NumInits && !hadError) - ILE->setInit(Init, - new (SemaRef.Context) ImplicitValueInitExpr(ElementType)); + Sema::OwningExprResult ElementInit + = InitSeq.Perform(SemaRef, ElementEntity, Kind, + Sema::MultiExprArg(SemaRef, 0, 0)); + if (ElementInit.isInvalid()) { + hadError = true; + return; + } + + if (hadError) { + // Do nothing + } else if (Init < NumInits) { + ILE->setInit(Init, ElementInit.takeAs()); + } else if (InitSeq.getKind() + == InitializationSequence::ConstructorInitialization) { + // Value-initialization requires a constructor call, so + // extend the initializer list to include the constructor + // call and make a note that we'll need to take another pass + // through the initializer list. + ILE->updateInit(Init, ElementInit.takeAs()); + RequiresSecondPass = true; + } } else if (InitListExpr *InnerILE - = dyn_cast(ILE->getInit(Init))) - FillInValueInitializations(InnerILE); + = dyn_cast(ILE->getInit(Init))) + FillInValueInitializations(ElementEntity, InnerILE, RequiresSecondPass); } } -InitListChecker::InitListChecker(Sema &S, InitListExpr *IL, QualType &T) +InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, + InitListExpr *IL, QualType &T) : SemaRef(S) { hadError = false; @@ -511,8 +435,13 @@ InitListChecker::InitListChecker(Sema &S, InitListExpr *IL, QualType &T) CheckExplicitInitList(IL, T, newIndex, FullyStructuredList, newStructuredIndex, /*TopLevelObject=*/true); - if (!hadError) - FillInValueInitializations(FullyStructuredList); + if (!hadError) { + bool RequiresSecondPass = false; + FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass); + if (RequiresSecondPass && !hadError) + FillInValueInitializations(Entity, FullyStructuredList, + RequiresSecondPass); + } } int InitListChecker::numArrayElements(QualType DeclType) { @@ -743,7 +672,7 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList, if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion) { if (SemaRef.PerformImplicitConversion(expr, ElemType, ICS, - "initializing")) + Sema::AA_Initializing)) hadError = true; UpdateStructuredListElement(StructuredList, StructuredIndex, expr); ++Index; @@ -783,7 +712,7 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList, } else { // We cannot initialize this element, so let // PerformCopyInitialization produce the appropriate diagnostic. - SemaRef.PerformCopyInitialization(expr, ElemType, "initializing"); + SemaRef.PerformCopyInitialization(expr, ElemType, Sema::AA_Initializing); hadError = true; ++Index; ++StructuredIndex; @@ -1358,22 +1287,33 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList, // may find nothing, or may find a member of an anonymous // struct/union. DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName); + FieldDecl *ReplacementField = 0; if (Lookup.first == Lookup.second) { - // Name lookup didn't find anything. - SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown) - << FieldName << CurrentObjectType; - ++Index; - return true; - } else if (!KnownField && isa(*Lookup.first) && - cast((*Lookup.first)->getDeclContext()) - ->isAnonymousStructOrUnion()) { - // Handle an field designator that refers to a member of an - // anonymous struct or union. - ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, - cast(*Lookup.first), - Field, FieldIndex); - D = DIE->getDesignator(DesigIdx); - } else { + // Name lookup didn't find anything. Determine whether this + // was a typo for another field name. + LookupResult R(SemaRef, FieldName, D->getFieldLoc(), + Sema::LookupMemberName); + if (SemaRef.CorrectTypo(R, /*Scope=*/0, /*SS=*/0, RT->getDecl()) && + (ReplacementField = R.getAsSingle()) && + ReplacementField->getDeclContext()->getLookupContext() + ->Equals(RT->getDecl())) { + SemaRef.Diag(D->getFieldLoc(), + diag::err_field_designator_unknown_suggest) + << FieldName << CurrentObjectType << R.getLookupName() + << CodeModificationHint::CreateReplacement(D->getFieldLoc(), + R.getLookupName().getAsString()); + } else { + SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown) + << FieldName << CurrentObjectType; + ++Index; + return true; + } + } else if (!KnownField) { + // Determine whether we found a field at all. + ReplacementField = dyn_cast(*Lookup.first); + } + + if (!ReplacementField) { // Name lookup found something, but it wasn't a field. SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield) << FieldName; @@ -1382,6 +1322,32 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList, ++Index; return true; } + + if (!KnownField && + cast((ReplacementField)->getDeclContext()) + ->isAnonymousStructOrUnion()) { + // Handle an field designator that refers to a member of an + // anonymous struct or union. + ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, + ReplacementField, + Field, FieldIndex); + D = DIE->getDesignator(DesigIdx); + } else if (!KnownField) { + // The replacement field comes from typo correction; find it + // in the list of fields. + FieldIndex = 0; + Field = RT->getDecl()->field_begin(); + for (; Field != FieldEnd; ++Field) { + if (Field->isUnnamedBitfield()) + continue; + + if (ReplacementField == *Field || + Field->getIdentifier() == ReplacementField->getIdentifier()) + break; + + ++FieldIndex; + } + } } else if (!KnownField && cast((*Field)->getDeclContext()) ->isAnonymousStructOrUnion()) { @@ -1844,101 +1810,27 @@ Sema::OwningExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, return Owned(DIE); } -bool Sema::CheckInitList(InitListExpr *&InitList, QualType &DeclType) { - InitListChecker CheckInitList(*this, InitList, DeclType); +bool Sema::CheckInitList(const InitializedEntity &Entity, + InitListExpr *&InitList, QualType &DeclType) { + InitListChecker CheckInitList(*this, Entity, InitList, DeclType); if (!CheckInitList.HadError()) InitList = CheckInitList.getFullyStructuredList(); return CheckInitList.HadError(); } -/// \brief Diagnose any semantic errors with value-initialization of -/// the given type. -/// -/// Value-initialization effectively zero-initializes any types -/// without user-declared constructors, and calls the default -/// constructor for a for any type that has a user-declared -/// constructor (C++ [dcl.init]p5). Value-initialization can fail when -/// a type with a user-declared constructor does not have an -/// accessible, non-deleted default constructor. In C, everything can -/// be value-initialized, which corresponds to C's notion of -/// initializing objects with static storage duration when no -/// initializer is provided for that object. -/// -/// \returns true if there was an error, false otherwise. -bool Sema::CheckValueInitialization(QualType Type, SourceLocation Loc) { - // C++ [dcl.init]p5: - // - // To value-initialize an object of type T means: - - // -- if T is an array type, then each element is value-initialized; - if (const ArrayType *AT = Context.getAsArrayType(Type)) - return CheckValueInitialization(AT->getElementType(), Loc); - - if (const RecordType *RT = Type->getAs()) { - if (CXXRecordDecl *ClassDecl = dyn_cast(RT->getDecl())) { - // -- if T is a class type (clause 9) with a user-declared - // constructor (12.1), then the default constructor for T is - // called (and the initialization is ill-formed if T has no - // accessible default constructor); - if (ClassDecl->hasUserDeclaredConstructor()) { - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); - - // FIXME: Poor location information - CXXConstructorDecl *Constructor - = PerformInitializationByConstructor(Type, - MultiExprArg(*this, 0, 0), - Loc, SourceRange(Loc), - DeclarationName(), - InitializationKind::CreateValue(Loc, Loc, Loc), - ConstructorArgs); - if (!Constructor) - return true; - - OwningExprResult Init - = BuildCXXConstructExpr(Loc, Type, Constructor, - move_arg(ConstructorArgs)); - if (Init.isInvalid()) - return true; - - // FIXME: Actually perform the value-initialization! - return false; - } - } - } - - if (Type->isReferenceType()) { - // C++ [dcl.init]p5: - // [...] A program that calls for default-initialization or - // value-initialization of an entity of reference type is - // ill-formed. [...] - // FIXME: Once we have code that goes through this path, add an actual - // diagnostic :) - } - - return false; -} - //===----------------------------------------------------------------------===// // Initialization entity //===----------------------------------------------------------------------===// -void InitializedEntity::InitDeclLoc() { - assert((Kind == EK_Variable || Kind == EK_Parameter || Kind == EK_Member) && - "InitDeclLoc cannot be used with non-declaration entities."); - - if (TypeSourceInfo *DI = VariableOrMember->getTypeSourceInfo()) { - TL = DI->getTypeLoc(); - return; - } - - // FIXME: Once we've gone through the effort to create the fake - // TypeSourceInfo, should we cache it in the declaration? - // (If not, we "leak" it). - TypeSourceInfo *DI = VariableOrMember->getASTContext() - .CreateTypeSourceInfo(VariableOrMember->getType()); - DI->getTypeLoc().initialize(VariableOrMember->getLocation()); - TL = DI->getTypeLoc(); +InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index, + const InitializedEntity &Parent) + : Kind(EK_ArrayOrVectorElement), Parent(&Parent), Index(Index) +{ + if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) + Type = AT->getElementType(); + else + Type = Parent.getType()->getAs()->getElementType(); } InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, @@ -1947,13 +1839,54 @@ InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, InitializedEntity Result; Result.Kind = EK_Base; Result.Base = Base; - // FIXME: CXXBaseSpecifier should store a TypeLoc. - TypeSourceInfo *DI = Context.CreateTypeSourceInfo(Base->getType()); - DI->getTypeLoc().initialize(Base->getSourceRange().getBegin()); - Result.TL = DI->getTypeLoc(); + Result.Type = Base->getType(); return Result; } +DeclarationName InitializedEntity::getName() const { + switch (getKind()) { + case EK_Parameter: + if (!VariableOrMember) + return DeclarationName(); + // Fall through + + case EK_Variable: + case EK_Member: + return VariableOrMember->getDeclName(); + + case EK_Result: + case EK_Exception: + case EK_New: + case EK_Temporary: + case EK_Base: + case EK_ArrayOrVectorElement: + return DeclarationName(); + } + + // Silence GCC warning + return DeclarationName(); +} + +DeclaratorDecl *InitializedEntity::getDecl() const { + switch (getKind()) { + case EK_Variable: + case EK_Parameter: + case EK_Member: + return VariableOrMember; + + case EK_Result: + case EK_Exception: + case EK_New: + case EK_Temporary: + case EK_Base: + case EK_ArrayOrVectorElement: + return 0; + } + + // Silence GCC warning + return 0; +} + //===----------------------------------------------------------------------===// // Initialization sequence //===----------------------------------------------------------------------===// @@ -1971,6 +1904,8 @@ void InitializationSequence::Step::Destroy() { case SK_ListInitialization: case SK_ConstructorInitialization: case SK_ZeroInitialization: + case SK_CAssignment: + case SK_StringInit: break; case SK_ConversionSequence: @@ -2056,6 +1991,20 @@ void InitializationSequence::AddZeroInitializationStep(QualType T) { Steps.push_back(S); } +void InitializationSequence::AddCAssignmentStep(QualType T) { + Step S; + S.Kind = SK_CAssignment; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddStringInitStep(QualType T) { + Step S; + S.Kind = SK_StringInit; + S.Type = T; + Steps.push_back(S); +} + void InitializationSequence::SetOverloadFailure(FailureKind Failure, OverloadingResult Result) { SequenceKind = FailedSequence; @@ -2081,7 +2030,7 @@ static void TryListInitialization(Sema &S, // force us to perform more checking here. Sequence.setSequenceKind(InitializationSequence::ListInitialization); - QualType DestType = Entity.getType().getType(); + QualType DestType = Entity.getType(); // C++ [dcl.init]p13: // If T is a scalar type, then a declaration of the form @@ -2125,7 +2074,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, Expr *Initializer, bool AllowRValues, InitializationSequence &Sequence) { - QualType DestType = Entity.getType().getType(); + QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs()->getPointeeType(); QualType T1 = cv1T1.getUnqualifiedType(); QualType cv2T2 = Initializer->getType(); @@ -2273,7 +2222,7 @@ static void TryReferenceInitialization(Sema &S, InitializationSequence &Sequence) { Sequence.setSequenceKind(InitializationSequence::ReferenceBinding); - QualType DestType = Entity.getType().getType(); + QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs()->getPointeeType(); QualType T1 = cv1T1.getUnqualifiedType(); QualType cv2T2 = Initializer->getType(); @@ -2437,7 +2386,12 @@ static void TryReferenceInitialization(Sema &S, // this into an overloading ambiguity diagnostic. However, we need // to keep that set as an OverloadCandidateSet rather than as some // other kind of set. - Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed); + if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) + Sequence.SetOverloadFailure( + InitializationSequence::FK_ReferenceInitOverloadFailed, + ConvOvlResult); + else + Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed); return; } @@ -2463,7 +2417,8 @@ static void TryStringLiteralInitialization(Sema &S, const InitializationKind &Kind, Expr *Initializer, InitializationSequence &Sequence) { - // FIXME: Implement! + Sequence.setSequenceKind(InitializationSequence::StringInit); + Sequence.AddStringInitStep(Entity.getType()); } /// \brief Attempt initialization by constructor (C++ [dcl.init]), which @@ -2475,7 +2430,10 @@ static void TryConstructorInitialization(Sema &S, Expr **Args, unsigned NumArgs, QualType DestType, InitializationSequence &Sequence) { - Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization); + if (Kind.getKind() == InitializationKind::IK_Copy) + Sequence.setSequenceKind(InitializationSequence::UserDefinedConversion); + else + Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization); // Build the candidate set directly in the initialization sequence // structure, so that it will persist if we fail. @@ -2512,7 +2470,7 @@ static void TryConstructorInitialization(Sema &S, Constructor = cast(*Con); if (!Constructor->isInvalidDecl() && - Constructor->isConvertingConstructor(AllowExplicit)) { + (AllowExplicit || !Constructor->isExplicit())) { if (ConstructorTmpl) S.AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0, Args, NumArgs, CandidateSet); @@ -2535,9 +2493,13 @@ static void TryConstructorInitialization(Sema &S, // Add the constructor initialization step. Any cv-qualification conversion is // subsumed by the initialization. - Sequence.AddConstructorInitializationStep( + if (Kind.getKind() == InitializationKind::IK_Copy) { + Sequence.AddUserConversionStep(Best->Function, DestType); + } else { + Sequence.AddConstructorInitializationStep( cast(Best->Function), - DestType); + DestType); + } } /// \brief Attempt value initialization (C++ [dcl.init]p7). @@ -2548,7 +2510,7 @@ static void TryValueInitialization(Sema &S, // C++ [dcl.init]p5: // // To value-initialize an object of type T means: - QualType T = Entity.getType().getType(); + QualType T = Entity.getType(); // -- if T is an array type, then each element is value-initialized; while (const ArrayType *AT = S.Context.getAsArrayType(T)) @@ -2566,15 +2528,58 @@ static void TryValueInitialization(Sema &S, if (ClassDecl->hasUserDeclaredConstructor()) return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence); - // FIXME: non-union class type w/ non-trivial default constructor gets - // zero-initialized, then constructor gets called. + // -- if T is a (possibly cv-qualified) non-union class type + // without a user-provided constructor, then the object is + // zero-initialized and, if T’s implicitly-declared default + // constructor is non-trivial, that constructor is called. + if ((ClassDecl->getTagKind() == TagDecl::TK_class || + ClassDecl->getTagKind() == TagDecl::TK_struct) && + !ClassDecl->hasTrivialConstructor()) { + Sequence.AddZeroInitializationStep(Entity.getType()); + return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence); + } } } - Sequence.AddZeroInitializationStep(Entity.getType().getType()); + Sequence.AddZeroInitializationStep(Entity.getType()); Sequence.setSequenceKind(InitializationSequence::ZeroInitialization); } +/// \brief Attempt default initialization (C++ [dcl.init]p6). +static void TryDefaultInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + InitializationSequence &Sequence) { + assert(Kind.getKind() == InitializationKind::IK_Default); + + // C++ [dcl.init]p6: + // To default-initialize an object of type T means: + // - if T is an array type, each element is default-initialized; + QualType DestType = Entity.getType(); + while (const ArrayType *Array = S.Context.getAsArrayType(DestType)) + DestType = Array->getElementType(); + + // - if T is a (possibly cv-qualified) class type (Clause 9), the default + // constructor for T is called (and the initialization is ill-formed if + // T has no accessible default constructor); + if (DestType->isRecordType()) { + // FIXME: If a program calls for the default initialization of an object of + // a const-qualified type T, T shall be a class type with a user-provided + // default constructor. + return TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, + Sequence); + } + + // - otherwise, no initialization is performed. + Sequence.setSequenceKind(InitializationSequence::NoInitialization); + + // If a program calls for the default initialization of an object of + // a const-qualified type T, T shall be a class type with a user-provided + // default constructor. + if (DestType.isConstQualified()) + Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); +} + /// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]), /// which enumerates all conversion functions and performs overload resolution /// to select the best. @@ -2585,7 +2590,7 @@ static void TryUserDefinedConversion(Sema &S, InitializationSequence &Sequence) { Sequence.setSequenceKind(InitializationSequence::UserDefinedConversion); - QualType DestType = Entity.getType().getType(); + QualType DestType = Entity.getType(); assert(!DestType->isReferenceType() && "References are handled elsewhere"); QualType SourceType = Initializer->getType(); assert((DestType->isRecordType() || SourceType->isRecordType()) && @@ -2632,43 +2637,49 @@ static void TryUserDefinedConversion(Sema &S, } } } - + + SourceLocation DeclLoc = Initializer->getLocStart(); + if (const RecordType *SourceRecordType = SourceType->getAs()) { // The type we're converting from is a class type, enumerate its conversion // functions. - CXXRecordDecl *SourceRecordDecl - = cast(SourceRecordType->getDecl()); - - const UnresolvedSet *Conversions - = SourceRecordDecl->getVisibleConversionFunctions(); - for (UnresolvedSet::iterator I = Conversions->begin(), - E = Conversions->end(); - I != E; ++I) { - NamedDecl *D = *I; - CXXRecordDecl *ActingDC = cast(D->getDeclContext()); - if (isa(D)) - D = cast(D)->getTargetDecl(); - - FunctionTemplateDecl *ConvTemplate = dyn_cast(D); - CXXConversionDecl *Conv; - if (ConvTemplate) - Conv = cast(ConvTemplate->getTemplatedDecl()); - else - Conv = cast(*I); + + // We can only enumerate the conversion functions for a complete type; if + // the type isn't complete, simply skip this step. + if (!S.RequireCompleteType(DeclLoc, SourceType, 0)) { + CXXRecordDecl *SourceRecordDecl + = cast(SourceRecordType->getDecl()); - if (AllowExplicit || !Conv->isExplicit()) { + const UnresolvedSet *Conversions + = SourceRecordDecl->getVisibleConversionFunctions(); + for (UnresolvedSet::iterator I = Conversions->begin(), + E = Conversions->end(); + I != E; ++I) { + NamedDecl *D = *I; + CXXRecordDecl *ActingDC = cast(D->getDeclContext()); + if (isa(D)) + D = cast(D)->getTargetDecl(); + + FunctionTemplateDecl *ConvTemplate = dyn_cast(D); + CXXConversionDecl *Conv; if (ConvTemplate) - S.AddTemplateConversionCandidate(ConvTemplate, ActingDC, Initializer, - DestType, CandidateSet); + Conv = cast(ConvTemplate->getTemplatedDecl()); else - S.AddConversionCandidate(Conv, ActingDC, Initializer, DestType, - CandidateSet); + Conv = cast(*I); + + if (AllowExplicit || !Conv->isExplicit()) { + if (ConvTemplate) + S.AddTemplateConversionCandidate(ConvTemplate, ActingDC, + Initializer, DestType, + CandidateSet); + else + S.AddConversionCandidate(Conv, ActingDC, Initializer, DestType, + CandidateSet); + } } } } - SourceLocation DeclLoc = Initializer->getLocStart(); - // Perform overload resolution. If it fails, return the failed result. OverloadCandidateSet::iterator Best; if (OverloadingResult Result @@ -2711,7 +2722,7 @@ static void TryImplicitConversion(Sema &S, Expr *Initializer, InitializationSequence &Sequence) { ImplicitConversionSequence ICS - = S.TryImplicitConversion(Initializer, Entity.getType().getType(), + = S.TryImplicitConversion(Initializer, Entity.getType(), /*SuppressUserConversions=*/true, /*AllowExplicit=*/false, /*ForceRValue=*/false, @@ -2723,7 +2734,7 @@ static void TryImplicitConversion(Sema &S, return; } - Sequence.AddConversionSequenceStep(ICS, Entity.getType().getType()); + Sequence.AddConversionSequenceStep(ICS, Entity.getType()); } InitializationSequence::InitializationSequence(Sema &S, @@ -2739,7 +2750,7 @@ InitializationSequence::InitializationSequence(Sema &S, // type is the type of the initializer expression. The source type is not // defined when the initializer is a braced-init-list or when it is a // parenthesized list of expressions. - QualType DestType = Entity.getType().getType(); + QualType DestType = Entity.getType(); if (DestType->isDependentType() || Expr::hasAnyTypeDependentArguments(Args, NumArgs)) { @@ -2749,7 +2760,7 @@ InitializationSequence::InitializationSequence(Sema &S, QualType SourceType; Expr *Initializer = 0; - if (Kind.getKind() == InitializationKind::IK_Copy) { + if (NumArgs == 1) { Initializer = Args[0]; if (!isa(Initializer)) SourceType = Initializer->getType(); @@ -2785,11 +2796,18 @@ InitializationSequence::InitializationSequence(Sema &S, } // - If the initializer is (), the object is value-initialized. - if (Kind.getKind() == InitializationKind::IK_Value) { + if (Kind.getKind() == InitializationKind::IK_Value || + (Kind.getKind() == InitializationKind::IK_Direct && NumArgs == 0)) { TryValueInitialization(S, Entity, Kind, *this); return; } + // Handle default initialization. + if (Kind.getKind() == InitializationKind::IK_Default){ + TryDefaultInitialization(S, Entity, Kind, *this); + return; + } + // - Otherwise, if the destination type is an array, the program is // ill-formed. if (const ArrayType *AT = Context.getAsArrayType(DestType)) { @@ -2800,6 +2818,13 @@ InitializationSequence::InitializationSequence(Sema &S, return; } + + // Handle initialization in C + if (!S.getLangOptions().CPlusPlus) { + setSequenceKind(CAssignment); + AddCAssignmentStep(DestType); + return; + } // - If the destination type is a (possibly cv-qualified) class type: if (DestType->isRecordType()) { @@ -2812,7 +2837,7 @@ InitializationSequence::InitializationSequence(Sema &S, (Context.hasSameUnqualifiedType(SourceType, DestType) || S.IsDerivedFrom(SourceType, DestType)))) TryConstructorInitialization(S, Entity, Kind, Args, NumArgs, - Entity.getType().getType(), *this); + Entity.getType(), *this); // - Otherwise (i.e., for the remaining copy-initialization cases), // user-defined conversion sequences that can convert from the source // type to the destination type or (when a conversion function is @@ -2824,9 +2849,15 @@ InitializationSequence::InitializationSequence(Sema &S, return; } + if (NumArgs > 1) { + SetFailed(FK_TooManyInitsForScalar); + return; + } + assert(NumArgs == 1 && "Zero-argument case handled above"); + // - Otherwise, if the source type is a (possibly cv-qualified) class // type, conversion functions are considered. - if (SourceType->isRecordType()) { + if (!SourceType.isNull() && SourceType->isRecordType()) { TryUserDefinedConversion(S, Entity, Kind, Initializer, *this); return; } @@ -2836,6 +2867,7 @@ InitializationSequence::InitializationSequence(Sema &S, // conversions (Clause 4) will be used, if necessary, to convert the // initializer expression to the cv-unqualified version of the // destination type; no user-defined conversions are considered. + setSequenceKind(StandardConversion); TryImplicitConversion(S, Entity, Kind, Initializer, *this); } @@ -2849,6 +2881,158 @@ InitializationSequence::~InitializationSequence() { //===----------------------------------------------------------------------===// // Perform initialization //===----------------------------------------------------------------------===// +static Sema::AssignmentAction +getAssignmentAction(const InitializedEntity &Entity) { + switch(Entity.getKind()) { + case InitializedEntity::EK_Variable: + case InitializedEntity::EK_New: + return Sema::AA_Initializing; + + case InitializedEntity::EK_Parameter: + // FIXME: Can we tell when we're sending vs. passing? + return Sema::AA_Passing; + + case InitializedEntity::EK_Result: + return Sema::AA_Returning; + + case InitializedEntity::EK_Exception: + case InitializedEntity::EK_Base: + llvm_unreachable("No assignment action for C++-specific initialization"); + break; + + case InitializedEntity::EK_Temporary: + // FIXME: Can we tell apart casting vs. converting? + return Sema::AA_Casting; + + case InitializedEntity::EK_Member: + case InitializedEntity::EK_ArrayOrVectorElement: + return Sema::AA_Initializing; + } + + return Sema::AA_Converting; +} + +static bool shouldBindAsTemporary(const InitializedEntity &Entity, + bool IsCopy) { + switch (Entity.getKind()) { + case InitializedEntity::EK_Result: + case InitializedEntity::EK_Exception: + return !IsCopy; + + case InitializedEntity::EK_New: + case InitializedEntity::EK_Variable: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Member: + case InitializedEntity::EK_ArrayOrVectorElement: + return false; + + case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Temporary: + return true; + } + + llvm_unreachable("missed an InitializedEntity kind?"); +} + +/// \brief If we need to perform an additional copy of the initialized object +/// for this kind of entity (e.g., the result of a function or an object being +/// thrown), make the copy. +static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Sema::OwningExprResult CurInit) { + SourceLocation Loc; + + switch (Entity.getKind()) { + case InitializedEntity::EK_Result: + if (Entity.getType()->isReferenceType()) + return move(CurInit); + Loc = Entity.getReturnLoc(); + break; + + case InitializedEntity::EK_Exception: + Loc = Entity.getThrowLoc(); + break; + + case InitializedEntity::EK_Variable: + if (Entity.getType()->isReferenceType() || + Kind.getKind() != InitializationKind::IK_Copy) + return move(CurInit); + Loc = Entity.getDecl()->getLocation(); + break; + + case InitializedEntity::EK_Parameter: + // FIXME: Do we need this initialization for a parameter? + return move(CurInit); + + case InitializedEntity::EK_New: + case InitializedEntity::EK_Temporary: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Member: + case InitializedEntity::EK_ArrayOrVectorElement: + // We don't need to copy for any of these initialized entities. + return move(CurInit); + } + + Expr *CurInitExpr = (Expr *)CurInit.get(); + CXXRecordDecl *Class = 0; + if (const RecordType *Record = CurInitExpr->getType()->getAs()) + Class = cast(Record->getDecl()); + if (!Class) + return move(CurInit); + + // Perform overload resolution using the class's copy constructors. + DeclarationName ConstructorName + = S.Context.DeclarationNames.getCXXConstructorName( + S.Context.getCanonicalType(S.Context.getTypeDeclType(Class))); + DeclContext::lookup_iterator Con, ConEnd; + OverloadCandidateSet CandidateSet; + for (llvm::tie(Con, ConEnd) = Class->lookup(ConstructorName); + Con != ConEnd; ++Con) { + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = dyn_cast(*Con); + if (!Constructor || Constructor->isInvalidDecl() || + !Constructor->isCopyConstructor()) + continue; + + S.AddOverloadCandidate(Constructor, &CurInitExpr, 1, CandidateSet); + } + + OverloadCandidateSet::iterator Best; + switch (S.BestViableFunction(CandidateSet, Loc, Best)) { + case OR_Success: + break; + + case OR_No_Viable_Function: + S.Diag(Loc, diag::err_temp_copy_no_viable) + << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + S.PrintOverloadCandidates(CandidateSet, false); + return S.ExprError(); + + case OR_Ambiguous: + S.Diag(Loc, diag::err_temp_copy_ambiguous) + << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + S.PrintOverloadCandidates(CandidateSet, true); + return S.ExprError(); + + case OR_Deleted: + S.Diag(Loc, diag::err_temp_copy_deleted) + << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + S.Diag(Best->Function->getLocation(), diag::note_unavailable_here) + << Best->Function->isDeleted(); + return S.ExprError(); + } + + CurInit.release(); + return S.BuildCXXConstructExpr(Loc, CurInitExpr->getType(), + cast(Best->Function), + /*Elidable=*/true, + Sema::MultiExprArg(S, + (void**)&CurInitExpr, 1)); +} Action::OwningExprResult InitializationSequence::Perform(Sema &S, @@ -2866,9 +3050,9 @@ InitializationSequence::Perform(Sema &S, // If the declaration is a non-dependent, incomplete array type // that has an initializer, then its type will be completed once // the initializer is instantiated. - if (ResultType && !Entity.getType().getType()->isDependentType() && + if (ResultType && !Entity.getType()->isDependentType() && Args.size() == 1) { - QualType DeclType = Entity.getType().getType(); + QualType DeclType = Entity.getType(); if (const IncompleteArrayType *ArrayT = S.Context.getAsIncompleteArrayType(DeclType)) { // FIXME: We don't currently have the ability to accurately @@ -2880,11 +3064,15 @@ InitializationSequence::Perform(Sema &S, // bound. if (isa((Expr *)Args.get()[0])) { SourceRange Brackets; + // Scavange the location of the brackets from the entity, if we can. - if (isa(Entity.getType())) { - IncompleteArrayTypeLoc ArrayLoc - = cast(Entity.getType()); - Brackets = ArrayLoc.getBracketsRange(); + if (DeclaratorDecl *DD = Entity.getDecl()) { + if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) { + TypeLoc TL = TInfo->getTypeLoc(); + if (IncompleteArrayTypeLoc *ArrayLoc + = dyn_cast(&TL)) + Brackets = ArrayLoc->getBracketsRange(); + } } *ResultType @@ -2898,7 +3086,7 @@ InitializationSequence::Perform(Sema &S, } } - if (Kind.getKind() == InitializationKind::IK_Copy) + if (Kind.getKind() == InitializationKind::IK_Copy || Kind.isExplicitCast()) return Sema::OwningExprResult(S, Args.release()[0]); unsigned NumArgs = Args.size(); @@ -2909,34 +3097,58 @@ InitializationSequence::Perform(Sema &S, SourceLocation())); } - QualType DestType = Entity.getType().getType().getNonReferenceType(); + if (SequenceKind == NoInitialization) + return S.Owned((Expr *)0); + + QualType DestType = Entity.getType().getNonReferenceType(); + // FIXME: Ugly hack around the fact that Entity.getType() is not + // the same as Entity.getDecl()->getType() in cases involving type merging, + // and we want latter when it makes sense. if (ResultType) - *ResultType = Entity.getType().getType(); - - Sema::OwningExprResult CurInit(S); - // For copy initialization and any other initialization forms that - // only have a single initializer, we start with the (only) - // initializer we have. - // FIXME: DPG is not happy about this. There's confusion regarding whether - // we're supposed to start the conversion from the solitary initializer or - // from the set of arguments. - if (Kind.getKind() == InitializationKind::IK_Copy || - SequenceKind != ConstructorInitialization) { + *ResultType = Entity.getDecl() ? Entity.getDecl()->getType() : + Entity.getType(); + + Sema::OwningExprResult CurInit = S.Owned((Expr *)0); + + assert(!Steps.empty() && "Cannot have an empty initialization sequence"); + + // For initialization steps that start with a single initializer, + // grab the only argument out the Args and place it into the "current" + // initializer. + switch (Steps.front().Kind) { + case SK_ResolveAddressOfOverloadedFunction: + case SK_CastDerivedToBaseRValue: + case SK_CastDerivedToBaseLValue: + case SK_BindReference: + case SK_BindReferenceToTemporary: + case SK_UserConversion: + case SK_QualificationConversionLValue: + case SK_QualificationConversionRValue: + case SK_ConversionSequence: + case SK_ListInitialization: + case SK_CAssignment: + case SK_StringInit: assert(Args.size() == 1); - CurInit = Sema::OwningExprResult(S, Args.release()[0]); + CurInit = Sema::OwningExprResult(S, ((Expr **)(Args.get()))[0]->Retain()); if (CurInit.isInvalid()) return S.ExprError(); + break; + + case SK_ConstructorInitialization: + case SK_ZeroInitialization: + break; } // Walk through the computed steps for the initialization sequence, // performing the specified conversions along the way. + bool ConstructorInitRequiresZeroInit = false; for (step_iterator Step = step_begin(), StepEnd = step_end(); Step != StepEnd; ++Step) { if (CurInit.isInvalid()) return S.ExprError(); Expr *CurInitExpr = (Expr *)CurInit.get(); - QualType SourceType = CurInitExpr->getType(); + QualType SourceType = CurInitExpr? CurInitExpr->getType() : QualType(); switch (Step->Kind) { case SK_ResolveAddressOfOverloadedFunction: @@ -2969,7 +3181,7 @@ InitializationSequence::Perform(Sema &S, if (FieldDecl *BitField = CurInitExpr->getBitField()) { // References cannot bind to bit fields (C++ [dcl.init.ref]p5). S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield) - << Entity.getType().getType().isVolatileQualified() + << Entity.getType().isVolatileQualified() << BitField->getDeclName() << CurInitExpr->getSourceRange(); S.Diag(BitField->getLocation(), diag::note_bitfield_decl); @@ -2996,6 +3208,7 @@ InitializationSequence::Perform(Sema &S, // We have a user-defined conversion that invokes either a constructor // or a conversion function. CastExpr::CastKind CastKind = CastExpr::CK_Unknown; + bool IsCopy = false; if (CXXConstructorDecl *Constructor = dyn_cast(Step->Function)) { // Build a call to the selected constructor. @@ -3019,10 +3232,14 @@ InitializationSequence::Perform(Sema &S, return S.ExprError(); CastKind = CastExpr::CK_ConstructorConversion; + QualType Class = S.Context.getTypeDeclType(Constructor->getParent()); + if (S.Context.hasSameUnqualifiedType(SourceType, Class) || + S.IsDerivedFrom(SourceType, Class)) + IsCopy = true; } else { // Build a call to the conversion function. CXXConversionDecl *Conversion = cast(Step->Function); - + // FIXME: Should we move this initialization into a separate // derived-to-base conversion? I believe the answer is "no", because // we don't want to turn off access control here for c-style casts. @@ -3041,12 +3258,17 @@ InitializationSequence::Perform(Sema &S, CastKind = CastExpr::CK_UserDefinedConversion; } - CurInit = S.MaybeBindToTemporary(CurInit.takeAs()); + if (shouldBindAsTemporary(Entity, IsCopy)) + CurInit = S.MaybeBindToTemporary(CurInit.takeAs()); + CurInitExpr = CurInit.takeAs(); CurInit = S.Owned(new (S.Context) ImplicitCastExpr(CurInitExpr->getType(), CastKind, CurInitExpr, - false)); + false)); + + if (!IsCopy) + CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit)); break; } @@ -3061,7 +3283,7 @@ InitializationSequence::Perform(Sema &S, break; case SK_ConversionSequence: - if (S.PerformImplicitConversion(CurInitExpr, Step->Type, "converting", + if (S.PerformImplicitConversion(CurInitExpr, Step->Type, Sema::AA_Converting, false, false, *Step->ICS)) return S.ExprError(); @@ -3072,7 +3294,7 @@ InitializationSequence::Perform(Sema &S, case SK_ListInitialization: { InitListExpr *InitList = cast(CurInitExpr); QualType Ty = Step->Type; - if (S.CheckInitList(InitList, ResultType? *ResultType : Ty)) + if (S.CheckInitList(Entity, InitList, ResultType? *ResultType : Ty)) return S.ExprError(); CurInit.release(); @@ -3095,22 +3317,68 @@ InitializationSequence::Perform(Sema &S, return S.ExprError(); // Build the an expression that constructs a temporary. - CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, - move_arg(ConstructorArgs)); + CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + Constructor, + move_arg(ConstructorArgs), + ConstructorInitRequiresZeroInit); if (CurInit.isInvalid()) return S.ExprError(); - - CurInit = S.MaybeBindToTemporary(CurInit.takeAs()); + + bool Elidable + = cast((Expr *)CurInit.get())->isElidable(); + if (shouldBindAsTemporary(Entity, Elidable)) + CurInit = S.MaybeBindToTemporary(CurInit.takeAs()); + + if (!Elidable) + CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit)); break; } case SK_ZeroInitialization: { - if (Kind.getKind() == InitializationKind::IK_Value) + step_iterator NextStep = Step; + ++NextStep; + if (NextStep != StepEnd && + NextStep->Kind == SK_ConstructorInitialization) { + // The need for zero-initialization is recorded directly into + // the call to the object's constructor within the next step. + ConstructorInitRequiresZeroInit = true; + } else if (Kind.getKind() == InitializationKind::IK_Value && + S.getLangOptions().CPlusPlus && + !Kind.isImplicitValueInit()) { CurInit = S.Owned(new (S.Context) CXXZeroInitValueExpr(Step->Type, Kind.getRange().getBegin(), Kind.getRange().getEnd())); - else + } else { CurInit = S.Owned(new (S.Context) ImplicitValueInitExpr(Step->Type)); + } + break; + } + + case SK_CAssignment: { + QualType SourceType = CurInitExpr->getType(); + Sema::AssignConvertType ConvTy = + S.CheckSingleAssignmentConstraints(Step->Type, CurInitExpr); + + // If this is a call, allow conversion to a transparent union. + if (ConvTy != Sema::Compatible && + Entity.getKind() == InitializedEntity::EK_Parameter && + S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExpr) + == Sema::Compatible) + ConvTy = Sema::Compatible; + + if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), + Step->Type, SourceType, + CurInitExpr, getAssignmentAction(Entity))) + return S.ExprError(); + + CurInit.release(); + CurInit = S.Owned(CurInitExpr); + break; + } + + case SK_StringInit: { + QualType Ty = Step->Type; + CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, S); break; } } @@ -3129,7 +3397,7 @@ bool InitializationSequence::Diagnose(Sema &S, if (SequenceKind != FailedSequence) return false; - QualType DestType = Entity.getType().getType(); + QualType DestType = Entity.getType(); switch (Failure) { case FK_TooManyInitsForReference: S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits) @@ -3152,9 +3420,15 @@ bool InitializationSequence::Diagnose(Sema &S, case FK_UserConversionOverloadFailed: switch (FailedOverloadResult) { case OR_Ambiguous: - S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition) - << Args[0]->getType() << DestType.getNonReferenceType() - << Args[0]->getSourceRange(); + if (Failure == FK_UserConversionOverloadFailed) + S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition) + << Args[0]->getType() << DestType + << Args[0]->getSourceRange(); + else + S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous) + << DestType << Args[0]->getType() + << Args[0]->getSourceRange(); + S.PrintOverloadCandidates(FailedCandidateSet, true); break; @@ -3220,7 +3494,8 @@ bool InitializationSequence::Diagnose(Sema &S, break; case FK_ConversionFailed: - S.Diag(Kind.getLocation(), diag::err_cannot_initialize_decl_noname) + S.Diag(Kind.getLocation(), diag::err_init_conversion_failed) + << (int)Entity.getKind() << DestType << (Args[0]->isLvalue(S.Context) == Expr::LV_Valid) << Args[0]->getType() @@ -3228,12 +3503,16 @@ bool InitializationSequence::Diagnose(Sema &S, break; case FK_TooManyInitsForScalar: { - InitListExpr *InitList = cast(Args[0]); + SourceRange R; + + if (InitListExpr *InitList = dyn_cast(Args[0])) + R = SourceRange(InitList->getInit(1)->getLocStart(), + InitList->getLocEnd()); + else + R = SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd()); S.Diag(Kind.getLocation(), diag::err_excess_initializers) - << /*scalar=*/2 - << SourceRange(InitList->getInit(1)->getLocStart(), - InitList->getLocEnd()); + << /*scalar=*/2 << R; break; } @@ -3290,7 +3569,36 @@ bool InitializationSequence::Diagnose(Sema &S, } break; } + + case FK_DefaultInitOfConst: + S.Diag(Kind.getLocation(), diag::err_default_init_const) + << DestType; + break; } return true; } + +//===----------------------------------------------------------------------===// +// Initialization helper functions +//===----------------------------------------------------------------------===// +Sema::OwningExprResult +Sema::PerformCopyInitialization(const InitializedEntity &Entity, + SourceLocation EqualLoc, + OwningExprResult Init) { + if (Init.isInvalid()) + return ExprError(); + + Expr *InitE = (Expr *)Init.get(); + assert(InitE && "No initialization expression?"); + + if (EqualLoc.isInvalid()) + EqualLoc = InitE->getLocStart(); + + InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(), + EqualLoc); + InitializationSequence Seq(*this, Entity, Kind, &InitE, 1); + Init.release(); + return Seq.Perform(*this, Entity, Kind, + MultiExprArg(*this, (void**)&InitE, 1)); +} diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h index 2d4b01f..5eb819a 100644 --- a/lib/Sema/SemaInit.h +++ b/lib/Sema/SemaInit.h @@ -14,7 +14,7 @@ #define LLVM_CLANG_SEMA_INIT_H #include "SemaOverload.h" -#include "clang/AST/TypeLoc.h" +#include "clang/AST/Type.h" #include "clang/Parse/Action.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/PointerIntPair.h" @@ -47,72 +47,79 @@ public: /// \brief The entity being initialized is an exception object that /// is being thrown. EK_Exception, + /// \brief The entity being initialized is an object (or array of + /// objects) allocated via new. + EK_New, /// \brief The entity being initialized is a temporary object. EK_Temporary, /// \brief The entity being initialized is a base member subobject. EK_Base, /// \brief The entity being initialized is a non-static data member /// subobject. - EK_Member + EK_Member, + /// \brief The entity being initialized is an element of an array + /// or vector. + EK_ArrayOrVectorElement }; private: /// \brief The kind of entity being initialized. EntityKind Kind; - /// \brief The type of the object or reference being initialized along with - /// its location information. - TypeLoc TL; + /// \brief If non-NULL, the parent entity in which this + /// initialization occurs. + const InitializedEntity *Parent; + + /// \brief The type of the object or reference being initialized. + QualType Type; union { /// \brief When Kind == EK_Variable, EK_Parameter, or EK_Member, /// the VarDecl, ParmVarDecl, or FieldDecl, respectively. DeclaratorDecl *VariableOrMember; - /// \brief When Kind == EK_Result or EK_Exception, the location of the - /// 'return' or 'throw' keyword, respectively. When Kind == EK_Temporary, - /// the location where the temporary is being created. + /// \brief When Kind == EK_Result, EK_Exception, or EK_New, the + /// location of the 'return', 'throw', or 'new' keyword, + /// respectively. When Kind == EK_Temporary, the location where + /// the temporary is being created. unsigned Location; /// \brief When Kind == EK_Base, the base specifier that provides the /// base class. CXXBaseSpecifier *Base; + + /// \brief When Kind = EK_ArrayOrVectorElement, the index of the + /// array or vector element being initialized. + unsigned Index; }; InitializedEntity() { } /// \brief Create the initialization entity for a variable. InitializedEntity(VarDecl *Var) - : Kind(EK_Variable), - VariableOrMember(reinterpret_cast(Var)) - { - InitDeclLoc(); - } + : Kind(EK_Variable), Parent(0), Type(Var->getType()), + VariableOrMember(reinterpret_cast(Var)) { } /// \brief Create the initialization entity for a parameter. InitializedEntity(ParmVarDecl *Parm) - : Kind(EK_Parameter), - VariableOrMember(reinterpret_cast(Parm)) - { - InitDeclLoc(); - } + : Kind(EK_Parameter), Parent(0), Type(Parm->getType().getUnqualifiedType()), + VariableOrMember(reinterpret_cast(Parm)) { } - /// \brief Create the initialization entity for the result of a function, - /// throwing an object, or performing an explicit cast. - InitializedEntity(EntityKind Kind, SourceLocation Loc, TypeLoc TL) - : Kind(Kind), TL(TL), Location(Loc.getRawEncoding()) { } + /// \brief Create the initialization entity for the result of a + /// function, throwing an object, performing an explicit cast, or + /// initializing a parameter for which there is no declaration. + InitializedEntity(EntityKind Kind, SourceLocation Loc, QualType Type) + : Kind(Kind), Parent(0), Type(Type), Location(Loc.getRawEncoding()) { } /// \brief Create the initialization entity for a member subobject. - InitializedEntity(FieldDecl *Member) - : Kind(EK_Member), - VariableOrMember(reinterpret_cast(Member)) - { - InitDeclLoc(); - } - - /// \brief Initialize type-location information from a declaration. - void InitDeclLoc(); + InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent) + : Kind(EK_Member), Parent(Parent), Type(Member->getType()), + VariableOrMember(reinterpret_cast(Member)) { } + /// \brief Create the initialization entity for an array element. + InitializedEntity(ASTContext &Context, unsigned Index, + const InitializedEntity &Parent); + public: /// \brief Create the initialization entity for a variable. static InitializedEntity InitializeVariable(VarDecl *Var) { @@ -124,38 +131,69 @@ public: return InitializedEntity(Parm); } + /// \brief Create the initialization entity for a parameter that is + /// only known by its type. + static InitializedEntity InitializeParameter(QualType Type) { + return InitializedEntity(EK_Parameter, SourceLocation(), Type); + } + /// \brief Create the initialization entity for the result of a function. static InitializedEntity InitializeResult(SourceLocation ReturnLoc, - TypeLoc TL) { - return InitializedEntity(EK_Result, ReturnLoc, TL); + QualType Type) { + return InitializedEntity(EK_Result, ReturnLoc, Type); } /// \brief Create the initialization entity for an exception object. static InitializedEntity InitializeException(SourceLocation ThrowLoc, - TypeLoc TL) { - return InitializedEntity(EK_Exception, ThrowLoc, TL); + QualType Type) { + return InitializedEntity(EK_Exception, ThrowLoc, Type); + } + + /// \brief Create the initialization entity for an object allocated via new. + static InitializedEntity InitializeNew(SourceLocation NewLoc, QualType Type) { + return InitializedEntity(EK_New, NewLoc, Type); } /// \brief Create the initialization entity for a temporary. - static InitializedEntity InitializeTemporary(EntityKind Kind, TypeLoc TL) { - return InitializedEntity(Kind, SourceLocation(), TL); + static InitializedEntity InitializeTemporary(QualType Type) { + return InitializedEntity(EK_Temporary, SourceLocation(), Type); } /// \brief Create the initialization entity for a base class subobject. static InitializedEntity InitializeBase(ASTContext &Context, CXXBaseSpecifier *Base); - /// \brief Create the initialize entity for a member subobject. - static InitializedEntity InitializeMember(FieldDecl *Member) { - return InitializedEntity(Member); + /// \brief Create the initialization entity for a member subobject. + static InitializedEntity InitializeMember(FieldDecl *Member, + const InitializedEntity *Parent = 0) { + return InitializedEntity(Member, Parent); } + /// \brief Create the initialization entity for an array element. + static InitializedEntity InitializeElement(ASTContext &Context, + unsigned Index, + const InitializedEntity &Parent) { + return InitializedEntity(Context, Index, Parent); + } + /// \brief Determine the kind of initialization. EntityKind getKind() const { return Kind; } + /// \brief Retrieve the parent of the entity being initialized, when + /// the initialization itself is occuring within the context of a + /// larger initialization. + const InitializedEntity *getParent() const { return Parent; } + /// \brief Retrieve type being initialized. - TypeLoc getType() const { return TL; } + QualType getType() const { return Type; } + /// \brief Retrieve the name of the entity being initialized. + DeclarationName getName() const; + + /// \brief Retrieve the variable, parameter, or field being + /// initialized. + DeclaratorDecl *getDecl() const; + /// \brief Determine the location of the 'return' keyword when initializing /// the result of a function call. SourceLocation getReturnLoc() const { @@ -169,6 +207,13 @@ public: assert(getKind() == EK_Exception && "No 'throw' location!"); return SourceLocation::getFromRawEncoding(Location); } + + /// \brief If this is already the initializer for an array or vector + /// element, sets the element index. + void setElementIndex(unsigned Index) { + assert(getKind() == EK_ArrayOrVectorElement); + this->Index = Index; + } }; /// \brief Describes the kind of initialization being performed, along with @@ -191,6 +236,7 @@ private: SIK_Copy = IK_Copy, ///< Copy initialization SIK_Default = IK_Default, ///< Default initialization SIK_Value = IK_Value, ///< Value initialization + SIK_ImplicitValue, ///< Implicit value initialization SIK_DirectCast, ///< Direct initialization due to a cast /// \brief Direct initialization due to a C-style or functional cast. SIK_DirectCStyleOrFunctionalCast @@ -242,15 +288,19 @@ public: /// \brief Create a value initialization. static InitializationKind CreateValue(SourceLocation InitLoc, SourceLocation LParenLoc, - SourceLocation RParenLoc) { - return InitializationKind(SIK_Value, InitLoc, LParenLoc, RParenLoc); + SourceLocation RParenLoc, + bool isImplicit = false) { + return InitializationKind(isImplicit? SIK_ImplicitValue : SIK_Value, + InitLoc, LParenLoc, RParenLoc); } /// \brief Determine the initialization kind. InitKind getKind() const { - if (Kind > SIK_Value) + if (Kind > SIK_ImplicitValue) return IK_Direct; - + if (Kind == SIK_ImplicitValue) + return IK_Value; + return (InitKind)Kind; } @@ -263,7 +313,12 @@ public: bool isCStyleOrFunctionalCast() const { return Kind == SIK_DirectCStyleOrFunctionalCast; } - + + /// \brief Determine whether this initialization is an implicit + /// value-initialization, e.g., as occurs during aggregate + /// initialization. + bool isImplicitValueInit() const { return Kind == SIK_ImplicitValue; } + /// \brief Retrieve the location at which initialization is occurring. SourceLocation getLocation() const { return Locations[0]; } @@ -319,7 +374,19 @@ public: ListInitialization, /// \brief Zero-initialization. - ZeroInitialization + ZeroInitialization, + + /// \brief No initialization required. + NoInitialization, + + /// \brief Standard conversion sequence. + StandardConversion, + + /// \brief C conversion sequence. + CAssignment, + + /// \brief String initialization + StringInit }; /// \brief Describes the kind of a particular step in an initialization @@ -350,7 +417,11 @@ public: /// \brief Perform initialization via a constructor. SK_ConstructorInitialization, /// \brief Zero-initialize the object - SK_ZeroInitialization + SK_ZeroInitialization, + /// \brief C assignment + SK_CAssignment, + /// \brief Initialization by string + SK_StringInit }; /// \brief A single step in the initialization sequence. @@ -420,7 +491,9 @@ public: /// \brief Overloading for a user-defined conversion failed. FK_UserConversionOverloadFailed, /// \brief Overloaded for initialization by constructor failed. - FK_ConstructorOverloadFailed + FK_ConstructorOverloadFailed, + /// \brief Default-initialization of a 'const' object. + FK_DefaultInitOfConst }; private: @@ -551,6 +624,16 @@ public: /// \brief Add a zero-initialization step. void AddZeroInitializationStep(QualType T); + /// \brief Add a C assignment step. + // + // FIXME: It isn't clear whether this should ever be needed; + // ideally, we would handle everything needed in C in the common + // path. However, that isn't the case yet. + void AddCAssignmentStep(QualType T); + + /// \brief Add a string init step. + void AddStringInitStep(QualType T); + /// \brief Note that this initialization sequence failed. void SetFailed(FailureKind Failure) { SequenceKind = FailedSequence; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 724e2fc..1419ceb 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -27,6 +27,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/ErrorHandling.h" +#include #include #include #include @@ -192,23 +193,83 @@ namespace { }; } +static bool IsAcceptableIDNS(NamedDecl *D, unsigned IDNS) { + return D->isInIdentifierNamespace(IDNS); +} + +static bool IsAcceptableOperatorName(NamedDecl *D, unsigned IDNS) { + return D->isInIdentifierNamespace(IDNS) && + !D->getDeclContext()->isRecord(); +} + +static bool IsAcceptableNestedNameSpecifierName(NamedDecl *D, unsigned IDNS) { + // This lookup ignores everything that isn't a type. + + // This is a fast check for the far most common case. + if (D->isInIdentifierNamespace(Decl::IDNS_Tag)) + return true; + + if (isa(D)) + D = cast(D)->getTargetDecl(); + + return isa(D); +} + +static bool IsAcceptableNamespaceName(NamedDecl *D, unsigned IDNS) { + // We don't need to look through using decls here because + // using decls aren't allowed to name namespaces. + + return isa(D) || isa(D); +} + +/// Gets the default result filter for the given lookup. +static inline +LookupResult::ResultFilter getResultFilter(Sema::LookupNameKind NameKind) { + switch (NameKind) { + case Sema::LookupOrdinaryName: + case Sema::LookupTagName: + case Sema::LookupMemberName: + case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping + case Sema::LookupUsingDeclName: + case Sema::LookupObjCProtocolName: + case Sema::LookupObjCImplementationName: + return &IsAcceptableIDNS; + + case Sema::LookupOperatorName: + return &IsAcceptableOperatorName; + + case Sema::LookupNestedNameSpecifierName: + return &IsAcceptableNestedNameSpecifierName; + + case Sema::LookupNamespaceName: + return &IsAcceptableNamespaceName; + } + + llvm_unreachable("unkknown lookup kind"); + return 0; +} + // Retrieve the set of identifier namespaces that correspond to a // specific kind of name lookup. -inline unsigned -getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind, - bool CPlusPlus) { +static inline unsigned getIDNS(Sema::LookupNameKind NameKind, + bool CPlusPlus, + bool Redeclaration) { unsigned IDNS = 0; switch (NameKind) { case Sema::LookupOrdinaryName: case Sema::LookupOperatorName: case Sema::LookupRedeclarationWithLinkage: IDNS = Decl::IDNS_Ordinary; - if (CPlusPlus) + if (CPlusPlus) { IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member; + if (Redeclaration) IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend; + } break; case Sema::LookupTagName: IDNS = Decl::IDNS_Tag; + if (CPlusPlus && Redeclaration) + IDNS |= Decl::IDNS_TagFriend; break; case Sema::LookupMemberName: @@ -238,6 +299,13 @@ getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind, return IDNS; } +void LookupResult::configure() { + IDNS = getIDNS(LookupKind, + SemaRef.getLangOptions().CPlusPlus, + isForRedeclaration()); + IsAcceptableFn = getResultFilter(LookupKind); +} + // Necessary because CXXBasePaths is not complete in Sema.h void LookupResult::deletePaths(CXXBasePaths *Paths) { delete Paths; @@ -377,8 +445,7 @@ static bool LookupDirect(LookupResult &R, const DeclContext *DC) { DeclContext::lookup_const_iterator I, E; for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) - if (Sema::isAcceptableLookupResult(*I, R.getLookupKind(), - R.getIdentifierNamespace())) + if (R.isAcceptableDecl(*I)) R.addDecl(*I), Found = true; return Found; @@ -424,19 +491,7 @@ static DeclContext *findOuterContext(Scope *S) { } bool Sema::CppLookupName(LookupResult &R, Scope *S) { - assert(getLangOptions().CPlusPlus && - "Can perform only C++ lookup"); - LookupNameKind NameKind = R.getLookupKind(); - unsigned IDNS - = getIdentifierNamespacesFromLookupNameKind(NameKind, /*CPlusPlus*/ true); - - // If we're testing for redeclarations, also look in the friend namespaces. - if (R.isForRedeclaration()) { - if (IDNS & Decl::IDNS_Tag) IDNS |= Decl::IDNS_TagFriend; - if (IDNS & Decl::IDNS_Ordinary) IDNS |= Decl::IDNS_OrdinaryFriend; - } - - R.setIdentifierNamespace(IDNS); + assert(getLangOptions().CPlusPlus && "Can perform only C++ lookup"); DeclarationName Name = R.getLookupName(); @@ -467,7 +522,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) { - if (isAcceptableLookupResult(*I, NameKind, IDNS)) { + if (R.isAcceptableDecl(*I)) { Found = true; R.addDecl(*I); } @@ -531,7 +586,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) { - if (isAcceptableLookupResult(*I, NameKind, IDNS)) { + if (R.isAcceptableDecl(*I)) { // We found something. Look for anything else in our scope // with this same name and in an acceptable identifier // namespace, so that we can construct an overload set if we @@ -597,47 +652,18 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { if (!getLangOptions().CPlusPlus) { // Unqualified name lookup in C/Objective-C is purely lexical, so // search in the declarations attached to the name. - unsigned IDNS = 0; - switch (NameKind) { - case Sema::LookupOrdinaryName: - IDNS = Decl::IDNS_Ordinary; - break; - case Sema::LookupTagName: - IDNS = Decl::IDNS_Tag; - break; - - case Sema::LookupMemberName: - IDNS = Decl::IDNS_Member; - break; - - case Sema::LookupOperatorName: - case Sema::LookupNestedNameSpecifierName: - case Sema::LookupNamespaceName: - case Sema::LookupUsingDeclName: - assert(false && "C does not perform these kinds of name lookup"); - break; - - case Sema::LookupRedeclarationWithLinkage: + if (NameKind == Sema::LookupRedeclarationWithLinkage) { // Find the nearest non-transparent declaration scope. while (!(S->getFlags() & Scope::DeclScope) || (S->getEntity() && static_cast(S->getEntity()) ->isTransparentContext())) S = S->getParent(); - IDNS = Decl::IDNS_Ordinary; - break; - - case Sema::LookupObjCProtocolName: - IDNS = Decl::IDNS_ObjCProtocol; - break; - - case Sema::LookupObjCImplementationName: - IDNS = Decl::IDNS_ObjCImplementation; - break; - } + unsigned IDNS = R.getIdentifierNamespace(); + // Scan up the scope chain looking for a decl that matches this // identifier that is in the appropriate namespace. This search // should not take long, as shadowing of names is uncommon, and @@ -864,17 +890,6 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx) { if (!R.getLookupName()) return false; - // If we're performing qualified name lookup (e.g., lookup into a - // struct), find fields as part of ordinary name lookup. - LookupNameKind NameKind = R.getLookupKind(); - unsigned IDNS - = getIdentifierNamespacesFromLookupNameKind(NameKind, - getLangOptions().CPlusPlus); - if (NameKind == LookupOrdinaryName) - IDNS |= Decl::IDNS_Member; - - R.setIdentifierNamespace(IDNS); - // Make sure that the declaration context is complete. assert((!isa(LookupCtx) || LookupCtx->isDependentContext() || @@ -1514,15 +1529,12 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, for (llvm::SmallVectorImpl::iterator I = Functions.begin(), E = Functions.end(); I != E; ++I) { - FunctionDecl *FDecl = dyn_cast(*I); - if (!FDecl) - FDecl = cast(*I)->getTemplatedDecl(); + // Look through any using declarations to find the underlying function. + NamedDecl *Fn = (*I)->getUnderlyingDecl(); - // Add the namespace in which this function was defined. Note - // that, if this is a member function, we do *not* consider the - // enclosing namespace of its class. - DeclContext *Ctx = FDecl->getDeclContext(); - CollectNamespace(AssociatedNamespaces, Ctx); + FunctionDecl *FDecl = dyn_cast(Fn); + if (!FDecl) + FDecl = cast(Fn)->getTemplatedDecl(); // Add the classes and namespaces associated with the parameter // types and return type of this function. @@ -1693,3 +1705,509 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, } } } + +//---------------------------------------------------------------------------- +// Search for all visible declarations. +//---------------------------------------------------------------------------- +VisibleDeclConsumer::~VisibleDeclConsumer() { } + +namespace { + +class ShadowContextRAII; + +class VisibleDeclsRecord { +public: + /// \brief An entry in the shadow map, which is optimized to store a + /// single declaration (the common case) but can also store a list + /// of declarations. + class ShadowMapEntry { + typedef llvm::SmallVector DeclVector; + + /// \brief Contains either the solitary NamedDecl * or a vector + /// of declarations. + llvm::PointerUnion DeclOrVector; + + public: + ShadowMapEntry() : DeclOrVector() { } + + void Add(NamedDecl *ND); + void Destroy(); + + // Iteration. + typedef NamedDecl **iterator; + iterator begin(); + iterator end(); + }; + +private: + /// \brief A mapping from declaration names to the declarations that have + /// this name within a particular scope. + typedef llvm::DenseMap ShadowMap; + + /// \brief A list of shadow maps, which is used to model name hiding. + std::list ShadowMaps; + + /// \brief The declaration contexts we have already visited. + llvm::SmallPtrSet VisitedContexts; + + friend class ShadowContextRAII; + +public: + /// \brief Determine whether we have already visited this context + /// (and, if not, note that we are going to visit that context now). + bool visitedContext(DeclContext *Ctx) { + return !VisitedContexts.insert(Ctx); + } + + /// \brief Determine whether the given declaration is hidden in the + /// current scope. + /// + /// \returns the declaration that hides the given declaration, or + /// NULL if no such declaration exists. + NamedDecl *checkHidden(NamedDecl *ND); + + /// \brief Add a declaration to the current shadow map. + void add(NamedDecl *ND) { ShadowMaps.back()[ND->getDeclName()].Add(ND); } +}; + +/// \brief RAII object that records when we've entered a shadow context. +class ShadowContextRAII { + VisibleDeclsRecord &Visible; + + typedef VisibleDeclsRecord::ShadowMap ShadowMap; + +public: + ShadowContextRAII(VisibleDeclsRecord &Visible) : Visible(Visible) { + Visible.ShadowMaps.push_back(ShadowMap()); + } + + ~ShadowContextRAII() { + for (ShadowMap::iterator E = Visible.ShadowMaps.back().begin(), + EEnd = Visible.ShadowMaps.back().end(); + E != EEnd; + ++E) + E->second.Destroy(); + + Visible.ShadowMaps.pop_back(); + } +}; + +} // end anonymous namespace + +void VisibleDeclsRecord::ShadowMapEntry::Add(NamedDecl *ND) { + if (DeclOrVector.isNull()) { + // 0 - > 1 elements: just set the single element information. + DeclOrVector = ND; + return; + } + + if (NamedDecl *PrevND = DeclOrVector.dyn_cast()) { + // 1 -> 2 elements: create the vector of results and push in the + // existing declaration. + DeclVector *Vec = new DeclVector; + Vec->push_back(PrevND); + DeclOrVector = Vec; + } + + // Add the new element to the end of the vector. + DeclOrVector.get()->push_back(ND); +} + +void VisibleDeclsRecord::ShadowMapEntry::Destroy() { + if (DeclVector *Vec = DeclOrVector.dyn_cast()) { + delete Vec; + DeclOrVector = ((NamedDecl *)0); + } +} + +VisibleDeclsRecord::ShadowMapEntry::iterator +VisibleDeclsRecord::ShadowMapEntry::begin() { + if (DeclOrVector.isNull()) + return 0; + + if (DeclOrVector.dyn_cast()) + return &reinterpret_cast(DeclOrVector); + + return DeclOrVector.get()->begin(); +} + +VisibleDeclsRecord::ShadowMapEntry::iterator +VisibleDeclsRecord::ShadowMapEntry::end() { + if (DeclOrVector.isNull()) + return 0; + + if (DeclOrVector.dyn_cast()) + return &reinterpret_cast(DeclOrVector) + 1; + + return DeclOrVector.get()->end(); +} + +NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) { + unsigned IDNS = ND->getIdentifierNamespace(); + std::list::reverse_iterator SM = ShadowMaps.rbegin(); + for (std::list::reverse_iterator SMEnd = ShadowMaps.rend(); + SM != SMEnd; ++SM) { + ShadowMap::iterator Pos = SM->find(ND->getDeclName()); + if (Pos == SM->end()) + continue; + + for (ShadowMapEntry::iterator I = Pos->second.begin(), + IEnd = Pos->second.end(); + I != IEnd; ++I) { + // A tag declaration does not hide a non-tag declaration. + if ((*I)->getIdentifierNamespace() == Decl::IDNS_Tag && + (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | + Decl::IDNS_ObjCProtocol))) + continue; + + // Protocols are in distinct namespaces from everything else. + if ((((*I)->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) + || (IDNS & Decl::IDNS_ObjCProtocol)) && + (*I)->getIdentifierNamespace() != IDNS) + continue; + + // We've found a declaration that hides this one. + return *I; + } + } + + return 0; +} + +static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, + bool QualifiedNameLookup, + VisibleDeclConsumer &Consumer, + VisibleDeclsRecord &Visited) { + // Make sure we don't visit the same context twice. + if (Visited.visitedContext(Ctx->getPrimaryContext())) + return; + + // Enumerate all of the results in this context. + for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx; + CurCtx = CurCtx->getNextContext()) { + for (DeclContext::decl_iterator D = CurCtx->decls_begin(), + DEnd = CurCtx->decls_end(); + D != DEnd; ++D) { + if (NamedDecl *ND = dyn_cast(*D)) + if (Result.isAcceptableDecl(ND)) { + Consumer.FoundDecl(ND, Visited.checkHidden(ND)); + Visited.add(ND); + } + + // Visit transparent contexts inside this context. + if (DeclContext *InnerCtx = dyn_cast(*D)) { + if (InnerCtx->isTransparentContext()) + LookupVisibleDecls(InnerCtx, Result, QualifiedNameLookup, + Consumer, Visited); + } + } + } + + // Traverse using directives for qualified name lookup. + if (QualifiedNameLookup) { + ShadowContextRAII Shadow(Visited); + DeclContext::udir_iterator I, E; + for (llvm::tie(I, E) = Ctx->getUsingDirectives(); I != E; ++I) { + LookupVisibleDecls((*I)->getNominatedNamespace(), Result, + QualifiedNameLookup, Consumer, Visited); + } + } + + // Traverse the contexts of inherited classes. + if (CXXRecordDecl *Record = dyn_cast(Ctx)) { + for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(), + BEnd = Record->bases_end(); + B != BEnd; ++B) { + QualType BaseType = B->getType(); + + // Don't look into dependent bases, because name lookup can't look + // there anyway. + if (BaseType->isDependentType()) + continue; + + const RecordType *Record = BaseType->getAs(); + if (!Record) + continue; + + // FIXME: It would be nice to be able to determine whether referencing + // a particular member would be ambiguous. For example, given + // + // struct A { int member; }; + // struct B { int member; }; + // struct C : A, B { }; + // + // void f(C *c) { c->### } + // + // accessing 'member' would result in an ambiguity. However, we + // could be smart enough to qualify the member with the base + // class, e.g., + // + // c->B::member + // + // or + // + // c->A::member + + // Find results in this base class (and its bases). + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(Record->getDecl(), Result, QualifiedNameLookup, + Consumer, Visited); + } + } + + // FIXME: Look into base classes in Objective-C! +} + +static void LookupVisibleDecls(Scope *S, LookupResult &Result, + UnqualUsingDirectiveSet &UDirs, + VisibleDeclConsumer &Consumer, + VisibleDeclsRecord &Visited) { + if (!S) + return; + + DeclContext *Entity = 0; + if (S->getEntity() && + !((DeclContext *)S->getEntity())->isFunctionOrMethod()) { + // Look into this scope's declaration context, along with any of its + // parent lookup contexts (e.g., enclosing classes), up to the point + // where we hit the context stored in the next outer scope. + Entity = (DeclContext *)S->getEntity(); + DeclContext *OuterCtx = findOuterContext(S); + + for (DeclContext *Ctx = Entity; Ctx && Ctx->getPrimaryContext() != OuterCtx; + Ctx = Ctx->getLookupParent()) { + if (Ctx->isFunctionOrMethod()) + continue; + + LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/false, + Consumer, Visited); + } + } else if (!S->getParent()) { + // Look into the translation unit scope. We walk through the translation + // unit's declaration context, because the Scope itself won't have all of + // the declarations if we loaded a precompiled header. + // FIXME: We would like the translation unit's Scope object to point to the + // translation unit, so we don't need this special "if" branch. However, + // doing so would force the normal C++ name-lookup code to look into the + // translation unit decl when the IdentifierInfo chains would suffice. + // Once we fix that problem (which is part of a more general "don't look + // in DeclContexts unless we have to" optimization), we can eliminate the + // TranslationUnit parameter entirely. + Entity = Result.getSema().Context.getTranslationUnitDecl(); + LookupVisibleDecls(Entity, Result, /*QualifiedNameLookup=*/false, + Consumer, Visited); + } else { + // Walk through the declarations in this Scope. + for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); + D != DEnd; ++D) { + if (NamedDecl *ND = dyn_cast((Decl *)((*D).get()))) + if (Result.isAcceptableDecl(ND)) { + Consumer.FoundDecl(ND, Visited.checkHidden(ND)); + Visited.add(ND); + } + } + } + + if (Entity) { + // Lookup visible declarations in any namespaces found by using + // directives. + UnqualUsingDirectiveSet::const_iterator UI, UEnd; + llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity); + for (; UI != UEnd; ++UI) + LookupVisibleDecls(const_cast(UI->getNominatedNamespace()), + Result, /*QualifiedNameLookup=*/false, Consumer, + Visited); + } + + // Lookup names in the parent scope. + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(S->getParent(), Result, UDirs, Consumer, Visited); +} + +void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, + VisibleDeclConsumer &Consumer) { + // Determine the set of using directives available during + // unqualified name lookup. + Scope *Initial = S; + UnqualUsingDirectiveSet UDirs; + if (getLangOptions().CPlusPlus) { + // Find the first namespace or translation-unit scope. + while (S && !isNamespaceOrTranslationUnitScope(S)) + S = S->getParent(); + + UDirs.visitScopeChain(Initial, S); + } + UDirs.done(); + + // Look for visible declarations. + LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); + VisibleDeclsRecord Visited; + ShadowContextRAII Shadow(Visited); + ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited); +} + +void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, + VisibleDeclConsumer &Consumer) { + LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); + VisibleDeclsRecord Visited; + ShadowContextRAII Shadow(Visited); + ::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true, Consumer, + Visited); +} + +//---------------------------------------------------------------------------- +// Typo correction +//---------------------------------------------------------------------------- + +namespace { +class TypoCorrectionConsumer : public VisibleDeclConsumer { + /// \brief The name written that is a typo in the source. + llvm::StringRef Typo; + + /// \brief The results found that have the smallest edit distance + /// found (so far) with the typo name. + llvm::SmallVector BestResults; + + /// \brief The best edit distance found so far. + unsigned BestEditDistance; + +public: + explicit TypoCorrectionConsumer(IdentifierInfo *Typo) + : Typo(Typo->getName()) { } + + virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding); + + typedef llvm::SmallVector::const_iterator iterator; + iterator begin() const { return BestResults.begin(); } + iterator end() const { return BestResults.end(); } + bool empty() const { return BestResults.empty(); } + + unsigned getBestEditDistance() const { return BestEditDistance; } +}; + +} + +void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding) { + // Don't consider hidden names for typo correction. + if (Hiding) + return; + + // Only consider entities with identifiers for names, ignoring + // special names (constructors, overloaded operators, selectors, + // etc.). + IdentifierInfo *Name = ND->getIdentifier(); + if (!Name) + return; + + // Compute the edit distance between the typo and the name of this + // entity. If this edit distance is not worse than the best edit + // distance we've seen so far, add it to the list of results. + unsigned ED = Typo.edit_distance(Name->getName()); + if (!BestResults.empty()) { + if (ED < BestEditDistance) { + // This result is better than any we've seen before; clear out + // the previous results. + BestResults.clear(); + BestEditDistance = ED; + } else if (ED > BestEditDistance) { + // This result is worse than the best results we've seen so far; + // ignore it. + return; + } + } else + BestEditDistance = ED; + + BestResults.push_back(ND); +} + +/// \brief Try to "correct" a typo in the source code by finding +/// visible declarations whose names are similar to the name that was +/// present in the source code. +/// +/// \param Res the \c LookupResult structure that contains the name +/// that was present in the source code along with the name-lookup +/// criteria used to search for the name. On success, this structure +/// will contain the results of name lookup. +/// +/// \param S the scope in which name lookup occurs. +/// +/// \param SS the nested-name-specifier that precedes the name we're +/// looking for, if present. +/// +/// \param MemberContext if non-NULL, the context in which to look for +/// a member access expression. +/// +/// \param EnteringContext whether we're entering the context described by +/// the nested-name-specifier SS. +/// +/// \returns true if the typo was corrected, in which case the \p Res +/// structure will contain the results of name lookup for the +/// corrected name. Otherwise, returns false. +bool Sema::CorrectTypo(LookupResult &Res, Scope *S, const CXXScopeSpec *SS, + DeclContext *MemberContext, bool EnteringContext) { + // We only attempt to correct typos for identifiers. + IdentifierInfo *Typo = Res.getLookupName().getAsIdentifierInfo(); + if (!Typo) + return false; + + // If the scope specifier itself was invalid, don't try to correct + // typos. + if (SS && SS->isInvalid()) + return false; + + // Never try to correct typos during template deduction or + // instantiation. + if (!ActiveTemplateInstantiations.empty()) + return false; + + TypoCorrectionConsumer Consumer(Typo); + if (MemberContext) + LookupVisibleDecls(MemberContext, Res.getLookupKind(), Consumer); + else if (SS && SS->isSet()) { + DeclContext *DC = computeDeclContext(*SS, EnteringContext); + if (!DC) + return false; + + LookupVisibleDecls(DC, Res.getLookupKind(), Consumer); + } else { + LookupVisibleDecls(S, Res.getLookupKind(), Consumer); + } + + if (Consumer.empty()) + return false; + + // Only allow a single, closest name in the result set (it's okay to + // have overloads of that name, though). + TypoCorrectionConsumer::iterator I = Consumer.begin(); + DeclarationName BestName = (*I)->getDeclName(); + ++I; + for(TypoCorrectionConsumer::iterator IEnd = Consumer.end(); I != IEnd; ++I) { + if (BestName != (*I)->getDeclName()) + return false; + } + + // BestName is the closest viable name to what the user + // typed. However, to make sure that we don't pick something that's + // way off, make sure that the user typed at least 3 characters for + // each correction. + unsigned ED = Consumer.getBestEditDistance(); + if (ED == 0 || (BestName.getAsIdentifierInfo()->getName().size() / ED) < 3) + return false; + + // Perform name lookup again with the name we chose, and declare + // success if we found something that was not ambiguous. + Res.clear(); + Res.setLookupName(BestName); + if (MemberContext) + LookupQualifiedName(Res, MemberContext); + else + LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false, + EnteringContext); + + if (Res.isAmbiguous()) { + Res.suppressDiagnostics(); + return false; + } + + return Res.getResultKind() != LookupResult::NotFound; +} diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 561cfdb..5892081 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -13,6 +13,7 @@ #include "Sema.h" #include "Lookup.h" +#include "SemaInit.h" #include "clang/Basic/Diagnostic.h" #include "clang/Lex/Preprocessor.h" #include "clang/AST/ASTContext.h" @@ -88,7 +89,7 @@ ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) { /// GetImplicitConversionName - Return the name of this kind of /// implicit conversion. const char* GetImplicitConversionName(ImplicitConversionKind Kind) { - static const char* Name[(int)ICK_Num_Conversion_Kinds] = { + static const char* const Name[(int)ICK_Num_Conversion_Kinds] = { "No conversion", "Lvalue-to-rvalue", "Array-to-pointer", @@ -451,7 +452,8 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType, QualType FromCanon = Context.getCanonicalType(From->getType().getUnqualifiedType()); QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType(); - if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) { + if (Constructor->isCopyConstructor() && + (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon))) { // Turn this into a "standard" conversion sequence, so that it // gets ranked with standard conversion sequences. ICS.ConversionKind = ImplicitConversionSequence::StandardConversion; @@ -915,6 +917,25 @@ BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr, Quals)); } +/// BuildSimilarlyQualifiedObjCObjectPointerType - In a pointer conversion from +/// the FromType, which is an objective-c pointer, to ToType, which may or may +/// not have the right set of qualifiers. +static QualType +BuildSimilarlyQualifiedObjCObjectPointerType(QualType FromType, + QualType ToType, + ASTContext &Context) { + QualType CanonFromType = Context.getCanonicalType(FromType); + QualType CanonToType = Context.getCanonicalType(ToType); + Qualifiers Quals = CanonFromType.getQualifiers(); + + // Exact qualifier match -> return the pointer type we're converting to. + if (CanonToType.getLocalQualifiers() == Quals) + return ToType; + + // Just build a canonical type that has the right qualifiers. + return Context.getQualifiedType(CanonToType.getLocalUnqualifiedType(), Quals); +} + static bool isNullPointerConstantForConversion(Expr *Expr, bool InOverloadResolution, ASTContext &Context) { @@ -992,13 +1013,20 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, return true; } - // Beyond this point, both types need to be pointers. + // Beyond this point, both types need to be pointers + // , including objective-c pointers. + QualType ToPointeeType = ToTypePtr->getPointeeType(); + if (FromType->isObjCObjectPointerType() && ToPointeeType->isVoidType()) { + ConvertedType = BuildSimilarlyQualifiedObjCObjectPointerType(FromType, + ToType, Context); + return true; + + } const PointerType *FromTypePtr = FromType->getAs(); if (!FromTypePtr) return false; QualType FromPointeeType = FromTypePtr->getPointeeType(); - QualType ToPointeeType = ToTypePtr->getPointeeType(); // An rvalue of type "pointer to cv T," where T is an object type, // can be converted to an rvalue of type "pointer to cv void" (C++ @@ -1774,7 +1802,16 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1, QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr); T1 = Context.getCanonicalType(T1); T2 = Context.getCanonicalType(T2); - if (Context.hasSameUnqualifiedType(T1, T2)) { + Qualifiers T1Quals, T2Quals; + QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals); + QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals); + if (UnqualT1 == UnqualT2) { + // If the type is an array type, promote the element qualifiers to the type + // for comparison. + if (isa(T1) && T1Quals) + T1 = Context.getQualifiedType(UnqualT1, T1Quals); + if (isa(T2) && T2Quals) + T2 = Context.getQualifiedType(UnqualT2, T2Quals); if (T2.isMoreQualifiedThan(T1)) return ImplicitConversionSequence::Better; else if (T1.isMoreQualifiedThan(T2)) @@ -1807,12 +1844,22 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1, QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr); T1 = Context.getCanonicalType(T1); T2 = Context.getCanonicalType(T2); + Qualifiers T1Quals, T2Quals; + QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals); + QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals); // If the types are the same, we won't learn anything by unwrapped // them. - if (Context.hasSameUnqualifiedType(T1, T2)) + if (UnqualT1 == UnqualT2) return ImplicitConversionSequence::Indistinguishable; + // If the type is an array type, promote the element qualifiers to the type + // for comparison. + if (isa(T1) && T1Quals) + T1 = Context.getQualifiedType(UnqualT1, T1Quals); + if (isa(T2) && T2Quals) + T2 = Context.getQualifiedType(UnqualT2, T2Quals); + ImplicitConversionSequence::CompareKind Result = ImplicitConversionSequence::Indistinguishable; while (UnwrapSimilarPointerTypes(T1, T2)) { @@ -2080,7 +2127,7 @@ Sema::TryCopyInitialization(Expr *From, QualType ToType, /// be true when the copy may be elided (C++ 12.8p15). Overload resolution works /// differently in C++0x for this case. bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType, - const char* Flavor, bool Elidable) { + AssignmentAction Action, bool Elidable) { if (!getLangOptions().CPlusPlus) { // In C, argument passing is the same as performing an assignment. QualType FromType = From->getType(); @@ -2092,7 +2139,7 @@ bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType, ConvTy = Compatible; return DiagnoseAssignmentResult(ConvTy, From->getLocStart(), ToType, - FromType, From, Flavor); + FromType, From, Action); } if (ToType->isReferenceType()) @@ -2102,13 +2149,13 @@ bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType, /*AllowExplicit=*/false, /*ForceRValue=*/false); - if (!PerformImplicitConversion(From, ToType, Flavor, + if (!PerformImplicitConversion(From, ToType, Action, /*AllowExplicit=*/false, Elidable)) return false; if (!DiagnoseMultipleUserDefinedConversion(From, ToType)) return Diag(From->getSourceRange().getBegin(), diag::err_typecheck_convert_incompatible) - << ToType << From->getType() << Flavor << From->getSourceRange(); + << ToType << From->getType() << Action << From->getSourceRange(); return true; } @@ -2229,7 +2276,7 @@ ImplicitConversionSequence Sema::TryContextuallyConvertToBool(Expr *From) { /// of the expression From to bool (C++0x [conv]p3). bool Sema::PerformContextuallyConvertToBool(Expr *&From) { ImplicitConversionSequence ICS = TryContextuallyConvertToBool(From); - if (!PerformImplicitConversion(From, Context.BoolTy, ICS, "converting")) + if (!PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting)) return false; if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy)) @@ -2622,7 +2669,14 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, Args, NumArgs, Specialization, Info)) { // FIXME: Record what happened with template argument deduction, so // that we can give the user a beautiful diagnostic. - (void)Result; + (void) Result; + + CandidateSet.push_back(OverloadCandidate()); + OverloadCandidate &Candidate = CandidateSet.back(); + Candidate.Function = FunctionTemplate->getTemplatedDecl(); + Candidate.Viable = false; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; return; } @@ -4430,6 +4484,9 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, bool FoundNonTemplateFunction = false; for (llvm::SmallVectorImpl::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) { + // Look through any using declarations to find the underlying function. + NamedDecl *Fn = (*I)->getUnderlyingDecl(); + // C++ [over.over]p3: // Non-member functions and static member functions match // targets of type "pointer-to-function" or "reference-to-function." @@ -4438,7 +4495,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, // Note that according to DR 247, the containing class does not matter. if (FunctionTemplateDecl *FunctionTemplate - = dyn_cast(*I)) { + = dyn_cast(Fn)) { if (CXXMethodDecl *Method = dyn_cast(FunctionTemplate->getTemplatedDecl())) { // Skip non-static function templates when converting to pointer, and @@ -4475,7 +4532,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, continue; } - if (CXXMethodDecl *Method = dyn_cast(*I)) { + if (CXXMethodDecl *Method = dyn_cast(Fn)) { // Skip non-static functions when converting to pointer, and static // when converting to member pointer. if (Method->isStatic() == IsMember) @@ -4487,7 +4544,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, } else if (IsMember) continue; - if (FunctionDecl *FunDecl = dyn_cast(*I)) { + if (FunctionDecl *FunDecl = dyn_cast(Fn)) { QualType ResultTy; if (Context.hasSameUnqualifiedType(FunctionType, FunDecl->getType()) || IsNoReturnConversion(Context, FunDecl->getType(), FunctionType, @@ -4558,6 +4615,93 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, return 0; } +/// \brief Given an expression that refers to an overloaded function, try to +/// resolve that overloaded function expression down to a single function. +/// +/// This routine can only resolve template-ids that refer to a single function +/// template, where that template-id refers to a single template whose template +/// arguments are either provided by the template-id or have defaults, +/// as described in C++0x [temp.arg.explicit]p3. +FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) { + // C++ [over.over]p1: + // [...] [Note: any redundant set of parentheses surrounding the + // overloaded function name is ignored (5.1). ] + Expr *OvlExpr = From->IgnoreParens(); + + // C++ [over.over]p1: + // [...] The overloaded function name can be preceded by the & + // operator. + if (UnaryOperator *UnOp = dyn_cast(OvlExpr)) { + if (UnOp->getOpcode() == UnaryOperator::AddrOf) + OvlExpr = UnOp->getSubExpr()->IgnoreParens(); + } + + bool HasExplicitTemplateArgs = false; + TemplateArgumentListInfo ExplicitTemplateArgs; + + llvm::SmallVector Fns; + + // Look into the overloaded expression. + if (UnresolvedLookupExpr *UL + = dyn_cast(OvlExpr)) { + Fns.append(UL->decls_begin(), UL->decls_end()); + if (UL->hasExplicitTemplateArgs()) { + HasExplicitTemplateArgs = true; + UL->copyTemplateArgumentsInto(ExplicitTemplateArgs); + } + } else if (UnresolvedMemberExpr *ME + = dyn_cast(OvlExpr)) { + Fns.append(ME->decls_begin(), ME->decls_end()); + if (ME->hasExplicitTemplateArgs()) { + HasExplicitTemplateArgs = true; + ME->copyTemplateArgumentsInto(ExplicitTemplateArgs); + } + } + + // If we didn't actually find any template-ids, we're done. + if (Fns.empty() || !HasExplicitTemplateArgs) + return 0; + + // Look through all of the overloaded functions, searching for one + // whose type matches exactly. + FunctionDecl *Matched = 0; + for (llvm::SmallVectorImpl::iterator I = Fns.begin(), + E = Fns.end(); I != E; ++I) { + // C++0x [temp.arg.explicit]p3: + // [...] In contexts where deduction is done and fails, or in contexts + // where deduction is not done, if a template argument list is + // specified and it, along with any default template arguments, + // identifies a single function template specialization, then the + // template-id is an lvalue for the function template specialization. + FunctionTemplateDecl *FunctionTemplate = cast(*I); + + // C++ [over.over]p2: + // If the name is a function template, template argument deduction is + // done (14.8.2.2), and if the argument deduction succeeds, the + // resulting template argument list is used to generate a single + // function template specialization, which is added to the set of + // overloaded functions considered. + // FIXME: We don't really want to build the specialization here, do we? + FunctionDecl *Specialization = 0; + TemplateDeductionInfo Info(Context); + if (TemplateDeductionResult Result + = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs, + Specialization, Info)) { + // FIXME: make a note of the failed deduction for diagnostics. + (void)Result; + continue; + } + + // Multiple matches; we can't resolve to a single declaration. + if (Matched) + return 0; + + Matched = Specialization; + } + + return Matched; +} + /// \brief Add a single candidate to the overload set. static void AddOverloadedCallCandidate(Sema &S, NamedDecl *Callee, @@ -4589,10 +4733,7 @@ static void AddOverloadedCallCandidate(Sema &S, /// \brief Add the overload candidates named by callee and/or found by argument /// dependent lookup to the given overload set. -void Sema::AddOverloadedCallCandidates(llvm::SmallVectorImpl &Fns, - DeclarationName &UnqualifiedName, - bool ArgumentDependentLookup, - const TemplateArgumentListInfo *ExplicitTemplateArgs, +void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet, bool PartialOverloading) { @@ -4615,28 +4756,99 @@ void Sema::AddOverloadedCallCandidates(llvm::SmallVectorImpl &Fns, // // then Y is empty. - if (ArgumentDependentLookup) { - for (unsigned I = 0; I < Fns.size(); ++I) { - assert(!Fns[I]->getDeclContext()->isRecord()); - assert(isa(Fns[I]) || - !Fns[I]->getDeclContext()->isFunctionOrMethod()); - assert(Fns[I]->getUnderlyingDecl()->isFunctionOrFunctionTemplate()); + if (ULE->requiresADL()) { + for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(), + E = ULE->decls_end(); I != E; ++I) { + assert(!(*I)->getDeclContext()->isRecord()); + assert(isa(*I) || + !(*I)->getDeclContext()->isFunctionOrMethod()); + assert((*I)->getUnderlyingDecl()->isFunctionOrFunctionTemplate()); } } #endif - for (llvm::SmallVectorImpl::iterator I = Fns.begin(), - E = Fns.end(); I != E; ++I) + // It would be nice to avoid this copy. + TemplateArgumentListInfo TABuffer; + const TemplateArgumentListInfo *ExplicitTemplateArgs = 0; + if (ULE->hasExplicitTemplateArgs()) { + ULE->copyTemplateArgumentsInto(TABuffer); + ExplicitTemplateArgs = &TABuffer; + } + + for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(), + E = ULE->decls_end(); I != E; ++I) AddOverloadedCallCandidate(*this, *I, ExplicitTemplateArgs, Args, NumArgs, CandidateSet, PartialOverloading); - if (ArgumentDependentLookup) - AddArgumentDependentLookupCandidates(UnqualifiedName, Args, NumArgs, + if (ULE->requiresADL()) + AddArgumentDependentLookupCandidates(ULE->getName(), Args, NumArgs, ExplicitTemplateArgs, CandidateSet, PartialOverloading); } + +static Sema::OwningExprResult Destroy(Sema &SemaRef, Expr *Fn, + Expr **Args, unsigned NumArgs) { + Fn->Destroy(SemaRef.Context); + for (unsigned Arg = 0; Arg < NumArgs; ++Arg) + Args[Arg]->Destroy(SemaRef.Context); + return SemaRef.ExprError(); +} + +/// Attempts to recover from a call where no functions were found. +/// +/// Returns true if new candidates were found. +static Sema::OwningExprResult +BuildRecoveryCallExpr(Sema &SemaRef, Expr *Fn, + UnresolvedLookupExpr *ULE, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc) { + + CXXScopeSpec SS; + if (ULE->getQualifier()) { + SS.setScopeRep(ULE->getQualifier()); + SS.setRange(ULE->getQualifierRange()); + } + + TemplateArgumentListInfo TABuffer; + const TemplateArgumentListInfo *ExplicitTemplateArgs = 0; + if (ULE->hasExplicitTemplateArgs()) { + ULE->copyTemplateArgumentsInto(TABuffer); + ExplicitTemplateArgs = &TABuffer; + } + + LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(), + Sema::LookupOrdinaryName); + if (SemaRef.DiagnoseEmptyLookup(/*Scope=*/0, SS, R)) + return Destroy(SemaRef, Fn, Args, NumArgs); + + assert(!R.empty() && "lookup results empty despite recovery"); + + // Build an implicit member call if appropriate. Just drop the + // casts and such from the call, we don't really care. + Sema::OwningExprResult NewFn = SemaRef.ExprError(); + if ((*R.begin())->isCXXClassMember()) + NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, R, ExplicitTemplateArgs); + else if (ExplicitTemplateArgs) + NewFn = SemaRef.BuildTemplateIdExpr(SS, R, false, *ExplicitTemplateArgs); + else + NewFn = SemaRef.BuildDeclarationNameExpr(SS, R, false); + + if (NewFn.isInvalid()) + return Destroy(SemaRef, Fn, Args, NumArgs); + + Fn->Destroy(SemaRef.Context); + + // This shouldn't cause an infinite loop because we're giving it + // an expression with non-empty lookup results, which should never + // end up here. + return SemaRef.ActOnCallExpr(/*Scope*/ 0, move(NewFn), LParenLoc, + Sema::MultiExprArg(SemaRef, (void**) Args, NumArgs), + CommaLocs, RParenLoc); +} /// ResolveOverloadedCallFn - Given the call expression that calls Fn /// (which eventually refers to the declaration Func) and the call @@ -4645,44 +4857,68 @@ void Sema::AddOverloadedCallCandidates(llvm::SmallVectorImpl &Fns, /// the function declaration produced by overload /// resolution. Otherwise, emits diagnostics, deletes all of the /// arguments and Fn, and returns NULL. -FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, - llvm::SmallVectorImpl &Fns, - DeclarationName UnqualifiedName, - const TemplateArgumentListInfo *ExplicitTemplateArgs, - SourceLocation LParenLoc, - Expr **Args, unsigned NumArgs, - SourceLocation *CommaLocs, - SourceLocation RParenLoc, - bool ArgumentDependentLookup) { +Sema::OwningExprResult +Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc) { +#ifndef NDEBUG + if (ULE->requiresADL()) { + // To do ADL, we must have found an unqualified name. + assert(!ULE->getQualifier() && "qualified name with ADL"); + + // We don't perform ADL for implicit declarations of builtins. + // Verify that this was correctly set up. + FunctionDecl *F; + if (ULE->decls_begin() + 1 == ULE->decls_end() && + (F = dyn_cast(*ULE->decls_begin())) && + F->getBuiltinID() && F->isImplicit()) + assert(0 && "performing ADL for builtin"); + + // We don't perform ADL in C. + assert(getLangOptions().CPlusPlus && "ADL enabled in C"); + } +#endif + OverloadCandidateSet CandidateSet; - // Add the functions denoted by Callee to the set of candidate - // functions. - AddOverloadedCallCandidates(Fns, UnqualifiedName, ArgumentDependentLookup, - ExplicitTemplateArgs, Args, NumArgs, - CandidateSet); + // Add the functions denoted by the callee to the set of candidate + // functions, including those from argument-dependent lookup. + AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet); + + // If we found nothing, try to recover. + // AddRecoveryCallCandidates diagnoses the error itself, so we just + // bailout out if it fails. + if (CandidateSet.empty()) + return BuildRecoveryCallExpr(*this, Fn, ULE, LParenLoc, Args, NumArgs, + CommaLocs, RParenLoc); + OverloadCandidateSet::iterator Best; switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) { - case OR_Success: - return Best->Function; + case OR_Success: { + FunctionDecl *FDecl = Best->Function; + Fn = FixOverloadedFunctionReference(Fn, FDecl); + return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc); + } case OR_No_Viable_Function: Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_no_viable_function_in_call) - << UnqualifiedName << Fn->getSourceRange(); + << ULE->getName() << Fn->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); break; case OR_Ambiguous: Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call) - << UnqualifiedName << Fn->getSourceRange(); + << ULE->getName() << Fn->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); break; case OR_Deleted: Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call) << Best->Function->isDeleted() - << UnqualifiedName + << ULE->getName() << Fn->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); break; @@ -4693,7 +4929,7 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, Fn->Destroy(Context); for (unsigned Arg = 0; Arg < NumArgs; ++Arg) Args[Arg]->Destroy(Context); - return 0; + return ExprError(); } static bool IsOverloaded(const Sema::FunctionSet &Functions) { @@ -4787,10 +5023,16 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, return ExprError(); } else { // Convert the arguments. - if (PerformCopyInitialization(Input, - FnDecl->getParamDecl(0)->getType(), - "passing")) + OwningExprResult InputInit + = PerformCopyInitialization(InitializedEntity::InitializeParameter( + FnDecl->getParamDecl(0)), + SourceLocation(), + move(input)); + if (InputInit.isInvalid()) return ExprError(); + + input = move(InputInit); + Input = (Expr *)input.get(); } // Determine the result type @@ -4817,7 +5059,7 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, // break out so that we will build the appropriate built-in // operator node. if (PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], "passing")) + Best->Conversions[0], AA_Passing)) return ExprError(); break; @@ -4954,17 +5196,40 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast(FnDecl)) { - if (PerformObjectArgumentInitialization(Args[0], Method) || - PerformCopyInitialization(Args[1], FnDecl->getParamDecl(0)->getType(), - "passing")) + OwningExprResult Arg1 + = PerformCopyInitialization( + InitializedEntity::InitializeParameter( + FnDecl->getParamDecl(0)), + SourceLocation(), + Owned(Args[1])); + if (Arg1.isInvalid()) + return ExprError(); + + if (PerformObjectArgumentInitialization(Args[0], Method)) return ExprError(); + + Args[1] = RHS = Arg1.takeAs(); } else { // Convert the arguments. - if (PerformCopyInitialization(Args[0], FnDecl->getParamDecl(0)->getType(), - "passing") || - PerformCopyInitialization(Args[1], FnDecl->getParamDecl(1)->getType(), - "passing")) + OwningExprResult Arg0 + = PerformCopyInitialization( + InitializedEntity::InitializeParameter( + FnDecl->getParamDecl(0)), + SourceLocation(), + Owned(Args[0])); + if (Arg0.isInvalid()) + return ExprError(); + + OwningExprResult Arg1 + = PerformCopyInitialization( + InitializedEntity::InitializeParameter( + FnDecl->getParamDecl(1)), + SourceLocation(), + Owned(Args[1])); + if (Arg1.isInvalid()) return ExprError(); + Args[0] = LHS = Arg0.takeAs(); + Args[1] = RHS = Arg1.takeAs(); } // Determine the result type @@ -4992,9 +5257,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // break out so that we will build the appropriate built-in // operator node. if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], "passing") || + Best->Conversions[0], AA_Passing) || PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], "passing")) + Best->Conversions[1], AA_Passing)) return ExprError(); break; @@ -5106,7 +5371,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, if (PerformObjectArgumentInitialization(Args[0], Method) || PerformCopyInitialization(Args[1], FnDecl->getParamDecl(0)->getType(), - "passing")) + AA_Passing)) return ExprError(); // Determine the result type @@ -5136,9 +5401,9 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // break out so that we will build the appropriate built-in // operator node. if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], "passing") || + Best->Conversions[0], AA_Passing) || PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], "passing")) + Best->Conversions[1], AA_Passing)) return ExprError(); break; @@ -5522,7 +5787,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // Pass the argument. QualType ProtoArgType = Proto->getArgType(i); - IsError |= PerformCopyInitialization(Arg, ProtoArgType, "passing"); + IsError |= PerformCopyInitialization(Arg, ProtoArgType, AA_Passing); } else { OwningExprResult DefArg = BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i)); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index de67a5f..b8928c3 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "SemaInit.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -95,7 +96,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (const CallExpr *CE = dyn_cast(E)) { // If the callee has attribute pure, const, or warn_unused_result, warn with // a more specific message to make it clear what is happening. - if (const FunctionDecl *FD = CE->getDirectCallee()) { + if (const Decl *FD = CE->getCalleeDecl()) { if (FD->getAttr()) { Diag(Loc, diag::warn_unused_call) << R1 << R2 << "warn_unused_result"; return; @@ -902,7 +903,7 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, AssignConvertType ConvTy = CheckSingleAssignmentConstraints(Context.VoidPtrTy, E); if (DiagnoseAssignmentResult(ConvTy, StarLoc, Context.VoidPtrTy, ETy, - E, "passing")) + E, AA_Passing)) return StmtError(); } return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E)); @@ -977,7 +978,6 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) { // we have a non-void block with an expression, continue checking - QualType RetValType = RetValExp->getType(); // C99 6.8.6.4p3(136): The return statement is not an assignment. The // overlap restriction of subclause 6.5.16.1 does not apply to the case of @@ -986,7 +986,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // In C++ the return statement is handled via a copy initialization. // the C version of which boils down to CheckSingleAssignmentConstraints. // FIXME: Leaks RetValExp. - if (PerformCopyInitialization(RetValExp, FnRetType, "returning")) + if (PerformCopyInitialization(RetValExp, FnRetType, AA_Returning)) return StmtError(); if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); @@ -1053,7 +1053,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) { << RetValExp->getSourceRange(); } - RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp, true); + RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp); } return Owned(new (Context) ReturnStmt(ReturnLoc, RetValExp)); } @@ -1092,21 +1092,28 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) { bool Elidable = getLangOptions().CPlusPlus0x ? IsReturnCopyElidable(Context, FnRetType, RetValExp) : false; + // FIXME: Elidable + (void)Elidable; // In C++ the return statement is handled via a copy initialization. // the C version of which boils down to CheckSingleAssignmentConstraints. - // FIXME: Leaks RetValExp on error. - if (PerformCopyInitialization(RetValExp, FnRetType, "returning", Elidable)){ - // We should still clean up our temporaries, even when we're failing! - RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp, true); + OwningExprResult Res = PerformCopyInitialization( + InitializedEntity::InitializeResult(ReturnLoc, + FnRetType), + SourceLocation(), + Owned(RetValExp)); + if (Res.isInvalid()) { + // FIXME: Cleanup temporaries here, anyway? return StmtError(); } - - if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); + + RetValExp = Res.takeAs(); + if (RetValExp) + CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); } if (RetValExp) - RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp, true); + RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp); return Owned(new (Context) ReturnStmt(ReturnLoc, RetValExp)); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index ac1b1ec..8c6aa6a 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -102,7 +102,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S, QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr); - LookupResult R(*this, TName, SourceLocation(), LookupOrdinaryName); + LookupResult R(*this, TName, Name.getSourceRange().getBegin(), + LookupOrdinaryName); R.suppressDiagnostics(); LookupTemplateName(R, S, SS, ObjectType, EnteringContext); if (R.empty()) @@ -202,6 +203,29 @@ void Sema::LookupTemplateName(LookupResult &Found, assert(!Found.isAmbiguous() && "Cannot handle template name-lookup ambiguities"); + if (Found.empty()) { + // If we did not find any names, attempt to correct any typos. + DeclarationName Name = Found.getLookupName(); + if (CorrectTypo(Found, S, &SS, LookupCtx)) { + FilterAcceptableTemplateNames(Context, Found); + if (!Found.empty() && isa(*Found.begin())) { + if (LookupCtx) + Diag(Found.getNameLoc(), diag::err_no_member_template_suggest) + << Name << LookupCtx << Found.getLookupName() << SS.getRange() + << CodeModificationHint::CreateReplacement(Found.getNameLoc(), + Found.getLookupName().getAsString()); + else + Diag(Found.getNameLoc(), diag::err_no_template_suggest) + << Name << Found.getLookupName() + << CodeModificationHint::CreateReplacement(Found.getNameLoc(), + Found.getLookupName().getAsString()); + } else + Found.clear(); + } else { + Found.clear(); + } + } + FilterAcceptableTemplateNames(Context, Found); if (Found.empty()) return; @@ -691,7 +715,27 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, if (Previous.begin() != Previous.end()) PrevDecl = *Previous.begin(); - if (PrevDecl && TUK == TUK_Friend) { + // If there is a previous declaration with the same name, check + // whether this is a valid redeclaration. + ClassTemplateDecl *PrevClassTemplate + = dyn_cast_or_null(PrevDecl); + + // We may have found the injected-class-name of a class template, + // class template partial specialization, or class template specialization. + // In these cases, grab the template that is being defined or specialized. + if (!PrevClassTemplate && PrevDecl && isa(PrevDecl) && + cast(PrevDecl)->isInjectedClassName()) { + PrevDecl = cast(PrevDecl->getDeclContext()); + PrevClassTemplate + = cast(PrevDecl)->getDescribedClassTemplate(); + if (!PrevClassTemplate && isa(PrevDecl)) { + PrevClassTemplate + = cast(PrevDecl) + ->getSpecializedTemplate(); + } + } + + if (TUK == TUK_Friend) { // C++ [namespace.memdef]p3: // [...] When looking for a prior declaration of a class or a function // declared as a friend, and when the name of the friend class or @@ -700,15 +744,16 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, DeclContext *OutermostContext = CurContext; while (!OutermostContext->isFileContext()) OutermostContext = OutermostContext->getLookupParent(); - - if (OutermostContext->Equals(PrevDecl->getDeclContext()) || - OutermostContext->Encloses(PrevDecl->getDeclContext())) { + + if (PrevDecl && + (OutermostContext->Equals(PrevDecl->getDeclContext()) || + OutermostContext->Encloses(PrevDecl->getDeclContext()))) { SemanticContext = PrevDecl->getDeclContext(); } else { // Declarations in outer scopes don't matter. However, the outermost // context we computed is the semantic context for our new // declaration. - PrevDecl = 0; + PrevDecl = PrevClassTemplate = 0; SemanticContext = OutermostContext; } @@ -717,30 +762,10 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // class template to the template in scope, because that would perform // checking of the template parameter lists that can't be performed // until the outer context is instantiated. - PrevDecl = 0; + PrevDecl = PrevClassTemplate = 0; } } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S)) - PrevDecl = 0; - - // If there is a previous declaration with the same name, check - // whether this is a valid redeclaration. - ClassTemplateDecl *PrevClassTemplate - = dyn_cast_or_null(PrevDecl); - - // We may have found the injected-class-name of a class template, - // class template partial specialization, or class template specialization. - // In these cases, grab the template that is being defined or specialized. - if (!PrevClassTemplate && PrevDecl && isa(PrevDecl) && - cast(PrevDecl)->isInjectedClassName()) { - PrevDecl = cast(PrevDecl->getDeclContext()); - PrevClassTemplate - = cast(PrevDecl)->getDescribedClassTemplate(); - if (!PrevClassTemplate && isa(PrevDecl)) { - PrevClassTemplate - = cast(PrevDecl) - ->getSpecializedTemplate(); - } - } + PrevDecl = PrevClassTemplate = 0; if (PrevClassTemplate) { // Ensure that the template parameter lists are compatible. @@ -2188,6 +2213,9 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param, Diag(SR.getBegin(), diag::err_template_arg_unnamed_type) << SR; Diag(Tag->getDecl()->getLocation(), diag::note_template_unnamed_type_here); return true; + } else if (Context.hasSameUnqualifiedType(Arg, Context.OverloadTy)) { + SourceRange SR = ArgInfo->getTypeLoc().getFullSourceRange(); + return Diag(SR.getBegin(), diag::err_template_arg_overload_type) << SR; } return false; @@ -2484,7 +2512,14 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // Check that we don't overflow the template parameter type. unsigned AllowedBits = Context.getTypeSize(IntegerType); - if (Value.getActiveBits() > AllowedBits) { + unsigned RequiredBits; + if (IntegerType->isUnsignedIntegerType()) + RequiredBits = Value.getActiveBits(); + else if (Value.isUnsigned()) + RequiredBits = Value.getActiveBits() + 1; + else + RequiredBits = Value.getMinSignedBits(); + if (RequiredBits > AllowedBits) { Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_too_large) << Value.toString(10) << Param->getType() diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index b4754db..21f7996 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -337,58 +337,6 @@ DeduceTemplateArguments(ASTContext &Context, return Sema::TDK_Success; } -/// \brief Returns a completely-unqualified array type, capturing the -/// qualifiers in Quals. -/// -/// \param Context the AST context in which the array type was built. -/// -/// \param T a canonical type that may be an array type. -/// -/// \param Quals will receive the full set of qualifiers that were -/// applied to the element type of the array. -/// -/// \returns if \p T is an array type, the completely unqualified array type -/// that corresponds to T. Otherwise, returns T. -static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T, - Qualifiers &Quals) { - assert(T.isCanonical() && "Only operates on canonical types"); - if (!isa(T)) { - Quals = T.getLocalQualifiers(); - return T.getLocalUnqualifiedType(); - } - - assert(!T.hasQualifiers() && "canonical array type has qualifiers!"); - - if (const ConstantArrayType *CAT = dyn_cast(T)) { - QualType Elt = getUnqualifiedArrayType(Context, CAT->getElementType(), - Quals); - if (Elt == CAT->getElementType()) - return T; - - return Context.getConstantArrayType(Elt, CAT->getSize(), - CAT->getSizeModifier(), 0); - } - - if (const IncompleteArrayType *IAT = dyn_cast(T)) { - QualType Elt = getUnqualifiedArrayType(Context, IAT->getElementType(), - Quals); - if (Elt == IAT->getElementType()) - return T; - - return Context.getIncompleteArrayType(Elt, IAT->getSizeModifier(), 0); - } - - const DependentSizedArrayType *DSAT = cast(T); - QualType Elt = getUnqualifiedArrayType(Context, DSAT->getElementType(), - Quals); - if (Elt == DSAT->getElementType()) - return T; - - return Context.getDependentSizedArrayType(Elt, DSAT->getSizeExpr()->Retain(), - DSAT->getSizeModifier(), 0, - SourceRange()); -} - /// \brief Deduce the template arguments by comparing the parameter type and /// the argument type (C++ [temp.deduct.type]). /// @@ -427,9 +375,11 @@ DeduceTemplateArguments(ASTContext &Context, // referred to by the reference) can be more cv-qualified than the // transformed A. if (TDF & TDF_ParamWithReferenceType) { - Qualifiers Quals = Param.getQualifiers(); - Quals.setCVRQualifiers(Quals.getCVRQualifiers() & Arg.getCVRQualifiers()); - Param = Context.getQualifiedType(Param.getUnqualifiedType(), Quals); + Qualifiers Quals; + QualType UnqualParam = Context.getUnqualifiedArrayType(Param, Quals); + Quals.setCVRQualifiers(Quals.getCVRQualifiers() & + Arg.getCVRQualifiersThroughArrayTypes()); + Param = Context.getQualifiedType(UnqualParam, Quals); } // If the parameter type is not dependent, there is nothing to deduce. @@ -459,7 +409,7 @@ DeduceTemplateArguments(ASTContext &Context, // FIXME: address spaces, ObjC GC qualifiers if (isa(Arg)) { Qualifiers Quals; - Arg = getUnqualifiedArrayType(Context, Arg, Quals); + Arg = Context.getUnqualifiedArrayType(Arg, Quals); if (Quals) { Arg = Context.getQualifiedType(Arg, Quals); RecanonicalizeArg = true; @@ -476,7 +426,7 @@ DeduceTemplateArguments(ASTContext &Context, } assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0"); - + assert(Arg != Context.OverloadTy && "Unresolved overloaded function"); QualType DeducedType = Arg; DeducedType.removeCVRQualifiers(Param.getCVRQualifiers()); if (RecanonicalizeArg) @@ -1506,15 +1456,39 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, ParamType->getAs()->getPointeeType()))) TDF |= TDF_DerivedClass; + // FIXME: C++0x [temp.deduct.call] paragraphs 6-9 deal with function + // pointer parameters. + + if (Context.hasSameUnqualifiedType(ArgType, Context.OverloadTy)) { + // We know that template argument deduction will fail if the argument is + // still an overloaded function. Check whether we can resolve this + // argument as a single function template specialization per + // C++ [temp.arg.explicit]p3. + FunctionDecl *ExplicitSpec + = ResolveSingleFunctionTemplateSpecialization(Args[I]); + Expr *ResolvedArg = 0; + if (ExplicitSpec) + ResolvedArg = FixOverloadedFunctionReference(Args[I], ExplicitSpec); + if (!ExplicitSpec || !ResolvedArg) { + // Template argument deduction fails if we can't resolve the overloaded + // function. + return TDK_FailedOverloadResolution; + } + + // Get the type of the resolved argument. + ArgType = ResolvedArg->getType(); + if (ArgType->isPointerType() || ArgType->isMemberPointerType()) + TDF |= TDF_IgnoreQualifiers; + + ResolvedArg->Destroy(Context); + } + if (TemplateDeductionResult Result = ::DeduceTemplateArguments(Context, TemplateParams, ParamType, ArgType, Info, Deduced, TDF)) return Result; - // FIXME: C++0x [temp.deduct.call] paragraphs 6-9 deal with function - // pointer parameters. - // FIXME: we need to check that the deduced A is the same as A, // modulo the various allowed differences. } @@ -1524,24 +1498,19 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, } /// \brief Deduce template arguments when taking the address of a function -/// template (C++ [temp.deduct.funcaddr]) or matching a +/// template (C++ [temp.deduct.funcaddr]) or matching a specialization to +/// a template. /// /// \param FunctionTemplate the function template for which we are performing /// template argument deduction. /// -/// \param HasExplicitTemplateArgs whether any template arguments were -/// explicitly specified. -/// -/// \param ExplicitTemplateArguments when @p HasExplicitTemplateArgs is true, -/// the explicitly-specified template arguments. -/// -/// \param NumExplicitTemplateArguments when @p HasExplicitTemplateArgs is true, -/// the number of explicitly-specified template arguments in -/// @p ExplicitTemplateArguments. This value may be zero. +/// \param ExplicitTemplateArguments the explicitly-specified template +/// arguments. /// /// \param ArgFunctionType the function type that will be used as the /// "argument" type (A) when performing template argument deduction from the -/// function template's function type. +/// function template's function type. This type may be NULL, if there is no +/// argument type to compare against, in C++0x [temp.arg.explicit]p3. /// /// \param Specialization if template argument deduction was successful, /// this will be set to the function template specialization produced by @@ -1578,14 +1547,16 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // Trap any errors that might occur. SFINAETrap Trap(*this); - // Deduce template arguments from the function type. - Deduced.resize(TemplateParams->size()); - if (TemplateDeductionResult Result - = ::DeduceTemplateArguments(Context, TemplateParams, - FunctionType, ArgFunctionType, Info, - Deduced, 0)) - return Result; - + if (!ArgFunctionType.isNull()) { + // Deduce template arguments from the function type. + Deduced.resize(TemplateParams->size()); + if (TemplateDeductionResult Result + = ::DeduceTemplateArguments(Context, TemplateParams, + FunctionType, ArgFunctionType, Info, + Deduced, 0)) + return Result; + } + return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, Specialization, Info); } @@ -1694,6 +1665,32 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, return Result; } +/// \brief Deduce template arguments for a function template when there is +/// nothing to deduce against (C++0x [temp.arg.explicit]p3). +/// +/// \param FunctionTemplate the function template for which we are performing +/// template argument deduction. +/// +/// \param ExplicitTemplateArguments the explicitly-specified template +/// arguments. +/// +/// \param Specialization if template argument deduction was successful, +/// this will be set to the function template specialization produced by +/// template argument deduction. +/// +/// \param Info the argument will be updated to provide additional information +/// about template argument deduction. +/// +/// \returns the result of template argument deduction. +Sema::TemplateDeductionResult +Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + const TemplateArgumentListInfo *ExplicitTemplateArgs, + FunctionDecl *&Specialization, + TemplateDeductionInfo &Info) { + return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, + QualType(), Specialization, Info); +} + /// \brief Stores the result of comparing the qualifiers of two types. enum DeductionQualifierComparison { NeitherMoreQualified = 0, @@ -2354,7 +2351,6 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, // None of these types have any template parameters in them. case Type::Builtin: - case Type::FixedWidthInt: case Type::VariableArray: case Type::FunctionNoProto: case Type::Record: diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index dddb93c8..d974f89 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -554,7 +554,6 @@ namespace { Sema::OwningExprResult TransformPredefinedExpr(PredefinedExpr *E); Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E); - Sema::OwningExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E); /// \brief Transforms a template type parameter type by performing @@ -785,7 +784,9 @@ Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr( assert(!cast(E->getParam()->getDeclContext())-> getDescribedFunctionTemplate() && "Default arg expressions are never formed in dependent cases."); - return SemaRef.Owned(E->Retain()); + return SemaRef.BuildCXXDefaultArgExpr(E->getUsedLocation(), + cast(E->getParam()->getDeclContext()), + E->getParam()); } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 8d74bd7..e909c4f 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -145,6 +145,11 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { if (Invalid) Typedef->setInvalidDecl(); + if (TypedefDecl *Prev = D->getPreviousDeclaration()) { + NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(Prev, TemplateArgs); + Typedef->setPreviousDeclaration(cast(InstPrev)); + } + Owner->addDecl(Typedef); return Typedef; @@ -396,7 +401,16 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { // FIXME: We have a problem here, because the nested call to Visit(ND) // will inject the thing that the friend references into the current // owner, which is wrong. - Decl *NewND = Visit(ND); + Decl *NewND; + + // Hack to make this work almost well pending a rewrite. + if (ND->getDeclContext()->isRecord()) + NewND = SemaRef.FindInstantiatedDecl(ND, TemplateArgs); + else if (D->wasSpecialization()) { + // Totally egregious hack to work around PR5866 + return 0; + } else + NewND = Visit(ND); if (!NewND) return 0; FU = cast(NewND); @@ -645,6 +659,12 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { CXXRecordDecl *PrevDecl = 0; if (D->isInjectedClassName()) PrevDecl = cast(Owner); + else if (D->getPreviousDeclaration()) { + NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getPreviousDeclaration(), + TemplateArgs); + if (!Prev) return 0; + PrevDecl = cast(Prev); + } CXXRecordDecl *Record = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner, @@ -675,7 +695,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { /// 1) instantiating function templates /// 2) substituting friend declarations /// FIXME: preserve function definitions in case #2 - Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, +Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, TemplateParameterList *TemplateParams) { // Check whether there is already a function template specialization for // this declaration. @@ -1149,6 +1169,8 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { if (NewUD->isInvalidDecl()) return NewUD; + bool isFunctionScope = Owner->isFunctionOrMethod(); + // Process the shadow decls. for (UsingDecl::shadow_iterator I = D->shadow_begin(), E = D->shadow_end(); I != E; ++I) { @@ -1164,6 +1186,9 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { UsingShadowDecl *InstShadow = SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget); SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow); + + if (isFunctionScope) + SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow); } return NewUD; diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 37f19f2..ed30229 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -308,7 +308,11 @@ static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){ Expr *E = static_cast(DS.getTypeRep()); assert(E && "Didn't get an expression for typeof?"); // TypeQuals handled by caller. - Result = Context.getTypeOfExprType(E); + Result = TheSema.BuildTypeofExprType(E); + if (Result.isNull()) { + Result = Context.IntTy; + TheDeclarator.setInvalidType(true); + } break; } case DeclSpec::TST_decltype: { @@ -1826,14 +1830,41 @@ QualType Sema::getQualifiedNameType(const CXXScopeSpec &SS, QualType T) { } QualType Sema::BuildTypeofExprType(Expr *E) { + if (E->getType() == Context.OverloadTy) { + // C++ [temp.arg.explicit]p3 allows us to resolve a template-id to a + // function template specialization wherever deduction cannot occur. + if (FunctionDecl *Specialization + = ResolveSingleFunctionTemplateSpecialization(E)) { + E = FixOverloadedFunctionReference(E, Specialization); + if (!E) + return QualType(); + } else { + Diag(E->getLocStart(), + diag::err_cannot_determine_declared_type_of_overloaded_function) + << false << E->getSourceRange(); + return QualType(); + } + } + return Context.getTypeOfExprType(E); } QualType Sema::BuildDecltypeType(Expr *E) { if (E->getType() == Context.OverloadTy) { - Diag(E->getLocStart(), - diag::err_cannot_determine_declared_type_of_overloaded_function); - return QualType(); + // C++ [temp.arg.explicit]p3 allows us to resolve a template-id to a + // function template specialization wherever deduction cannot occur. + if (FunctionDecl *Specialization + = ResolveSingleFunctionTemplateSpecialization(E)) { + E = FixOverloadedFunctionReference(E, Specialization); + if (!E) + return QualType(); + } else { + Diag(E->getLocStart(), + diag::err_cannot_determine_declared_type_of_overloaded_function) + << true << E->getSourceRange(); + return QualType(); + } } + return Context.getDecltypeType(E); } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index fd19987..208c885 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -956,8 +956,12 @@ public: // We have a reference to an unnamed field. assert(!Qualifier && "Can't have an unnamed field with a qualifier!"); + Expr *BaseExpr = Base.takeAs(); + if (getSema().PerformObjectMemberConversion(BaseExpr, Member)) + return getSema().ExprError(); + MemberExpr *ME = - new (getSema().Context) MemberExpr(Base.takeAs(), isArrow, + new (getSema().Context) MemberExpr(BaseExpr, isArrow, Member, MemberLoc, cast(Member)->getType()); return getSema().Owned(ME); @@ -1358,8 +1362,10 @@ public: /// By default, builds a new default-argument expression, which does not /// require any semantic analysis. Subclasses may override this routine to /// provide different behavior. - OwningExprResult RebuildCXXDefaultArgExpr(ParmVarDecl *Param) { - return getSema().Owned(CXXDefaultArgExpr::Create(getSema().Context, Param)); + OwningExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc, + ParmVarDecl *Param) { + return getSema().Owned(CXXDefaultArgExpr::Create(getSema().Context, Loc, + Param)); } /// \brief Build a new C++ zero-initialization expression. @@ -1655,7 +1661,7 @@ Sema::OwningStmtResult TreeTransform::TransformStmt(Stmt *S) { if (E.isInvalid()) return getSema().StmtError(); - return getSema().ActOnExprStmt(getSema().FullExpr(E)); + return getSema().ActOnExprStmt(getSema().MakeFullExpr(E)); } } @@ -2128,13 +2134,6 @@ QualType TreeTransform::TransformBuiltinType(TypeLocBuilder &TLB, } template -QualType -TreeTransform::TransformFixedWidthIntType(TypeLocBuilder &TLB, - FixedWidthIntTypeLoc T) { - return TransformTypeSpecType(TLB, T); -} - -template QualType TreeTransform::TransformComplexType(TypeLocBuilder &TLB, ComplexTypeLoc T) { // FIXME: recurse? @@ -3067,7 +3066,7 @@ TreeTransform::TransformIfStmt(IfStmt *S) { return SemaRef.StmtError(); } - Sema::FullExprArg FullCond(getSema().FullExpr(Cond)); + Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond)); // Transform the "then" branch. OwningStmtResult Then = getDerived().TransformStmt(S->getThen()); @@ -3110,7 +3109,7 @@ TreeTransform::TransformSwitchStmt(SwitchStmt *S) { return SemaRef.StmtError(); } - Sema::FullExprArg FullCond(getSema().FullExpr(Cond)); + Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond)); // Rebuild the switch statement. OwningStmtResult Switch = getDerived().RebuildSwitchStmtStart(FullCond, @@ -3147,7 +3146,7 @@ TreeTransform::TransformWhileStmt(WhileStmt *S) { return SemaRef.StmtError(); } - Sema::FullExprArg FullCond(getSema().FullExpr(Cond)); + Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond)); // Transform the body OwningStmtResult Body = getDerived().TransformStmt(S->getBody()); @@ -3229,9 +3228,9 @@ TreeTransform::TransformForStmt(ForStmt *S) { return SemaRef.Owned(S->Retain()); return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(), - move(Init), getSema().FullExpr(Cond), + move(Init), getSema().MakeFullExpr(Cond), ConditionVar, - getSema().FullExpr(Inc), + getSema().MakeFullExpr(Inc), S->getRParenLoc(), move(Body)); } @@ -3688,8 +3687,13 @@ TreeTransform::TransformMemberExpr(MemberExpr *E) { Base.get() == E->getBase() && Qualifier == E->getQualifier() && Member == E->getMemberDecl() && - !E->hasExplicitTemplateArgumentList()) + !E->hasExplicitTemplateArgumentList()) { + + // Mark it referenced in the new context regardless. + // FIXME: this is a bit instantiation-specific. + SemaRef.MarkDeclarationReferenced(E->getMemberLoc(), Member); return SemaRef.Owned(E->Retain()); + } TemplateArgumentListInfo TransArgs; if (E->hasExplicitTemplateArgumentList()) { @@ -4411,7 +4415,7 @@ TreeTransform::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { Param == E->getParam()) return SemaRef.Owned(E->Retain()); - return getDerived().RebuildCXXDefaultArgExpr(Param); + return getDerived().RebuildCXXDefaultArgExpr(E->getUsedLocation(), Param); } template @@ -4476,6 +4480,31 @@ TreeTransform::TransformCXXNewExpr(CXXNewExpr *E) { !ArgumentChanged) return SemaRef.Owned(E->Retain()); + if (!ArraySize.get()) { + // If no array size was specified, but the new expression was + // instantiated with an array type (e.g., "new T" where T is + // instantiated with "int[4]"), extract the outer bound from the + // array type as our array size. We do this with constant and + // dependently-sized array types. + const ArrayType *ArrayT = SemaRef.Context.getAsArrayType(AllocType); + if (!ArrayT) { + // Do nothing + } else if (const ConstantArrayType *ConsArrayT + = dyn_cast(ArrayT)) { + ArraySize + = SemaRef.Owned(new (SemaRef.Context) IntegerLiteral( + ConsArrayT->getSize(), + SemaRef.Context.getSizeType(), + /*FIXME:*/E->getLocStart())); + AllocType = ConsArrayT->getElementType(); + } else if (const DependentSizedArrayType *DepArrayT + = dyn_cast(ArrayT)) { + if (DepArrayT->getSizeExpr()) { + ArraySize = SemaRef.Owned(DepArrayT->getSizeExpr()->Retain()); + AllocType = DepArrayT->getElementType(); + } + } + } return getDerived().RebuildCXXNewExpr(E->getLocStart(), E->isGlobalNew(), /*FIXME:*/E->getLocStart(), @@ -4725,38 +4754,24 @@ TreeTransform::TransformCXXConstructExpr(CXXConstructExpr *E) { /// \brief Transform a C++ temporary-binding expression. /// -/// The transformation of a temporary-binding expression always attempts to -/// bind a new temporary variable to its subexpression, even if the -/// subexpression itself did not change, because the temporary variable itself -/// must be unique. +/// Since CXXBindTemporaryExpr nodes are implicitly generated, we just +/// transform the subexpression and return that. template Sema::OwningExprResult TreeTransform::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { - OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); - if (SubExpr.isInvalid()) - return SemaRef.ExprError(); - - return SemaRef.MaybeBindToTemporary(SubExpr.takeAs()); + return getDerived().TransformExpr(E->getSubExpr()); } /// \brief Transform a C++ expression that contains temporaries that should /// be destroyed after the expression is evaluated. /// -/// The transformation of a full expression always attempts to build a new -/// CXXExprWithTemporaries expression, even if the -/// subexpression itself did not change, because it will need to capture the -/// the new temporary variables introduced in the subexpression. +/// Since CXXExprWithTemporaries nodes are implicitly generated, we +/// just transform the subexpression and return that. template Sema::OwningExprResult TreeTransform::TransformCXXExprWithTemporaries( - CXXExprWithTemporaries *E) { - OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); - if (SubExpr.isInvalid()) - return SemaRef.ExprError(); - - return SemaRef.Owned( - SemaRef.MaybeCreateCXXExprWithTemporaries(SubExpr.takeAs(), - E->shouldDestroyTemporaries())); + CXXExprWithTemporaries *E) { + return getDerived().TransformExpr(E->getSubExpr()); } template @@ -5233,9 +5248,6 @@ TreeTransform::RebuildArrayType(QualType ElementType, break; } - if (SizeType.isNull()) - SizeType = SemaRef.Context.getFixedWidthIntType(Size->getBitWidth(), false); - IntegerLiteral ArraySize(*Size, SizeType, /*FIXME*/BracketsRange.getBegin()); return SemaRef.BuildArrayType(ElementType, SizeMod, &ArraySize, IndexTypeQuals, BracketsRange, -- cgit v1.1