diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema')
27 files changed, 5106 insertions, 1412 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp index e482172ca3eb..9efae6103a4a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -196,7 +196,12 @@ static ControlFlowKind CheckFallThrough(AnalysisContext &AC) {          continue;        }        Expr *CEE = C->getCallee()->IgnoreParenCasts(); -      if (getFunctionExtInfo(CEE->getType()).getNoReturn()) { +      QualType calleeType = CEE->getType(); +      if (calleeType == AC.getASTContext().BoundMemberTy) { +        calleeType = Expr::findBoundMemberType(CEE); +        assert(!calleeType.isNull() && "analyzing unresolved call?"); +      } +      if (getFunctionExtInfo(calleeType).getNoReturn()) {          NoReturnEdge = true;          HasFakeEdge = true;        } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) { diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp index 0f20d10b076a..5be16e7431c1 100644 --- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp @@ -309,6 +309,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {    case DeclSpec::TST_typeofExpr:  return "typeof";    case DeclSpec::TST_auto:        return "auto";    case DeclSpec::TST_decltype:    return "(decltype)"; +  case DeclSpec::TST_underlyingType: return "__underlying_type";    case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";    case DeclSpec::TST_error:       return "(error)";    } diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp index 867d78fef6a7..ae154aae2062 100644 --- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp @@ -15,6 +15,7 @@  #include "clang/Sema/SemaInternal.h"  #include "clang/AST/DeclCXX.h"  #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h"  #include "clang/AST/StmtObjC.h"  #include "clang/AST/StmtCXX.h"  #include "llvm/ADT/BitVector.h" @@ -126,18 +127,45 @@ static std::pair<unsigned,unsigned>        InDiag = diag::note_protected_by_cleanup;        OutDiag = diag::note_exits_cleanup;      } else if (isCPlusPlus) { -      // FIXME: In C++0x, we have to check more conditions than "did we -      // just give it an initializer?". See 6.7p3. -      if (VD->hasLocalStorage() && VD->hasInit()) -        InDiag = diag::note_protected_by_variable_init; - -      CanQualType T = VD->getType()->getCanonicalTypeUnqualified(); +      if (!VD->hasLocalStorage()) +        return std::make_pair(InDiag, OutDiag); +       +      ASTContext &Context = D->getASTContext(); +      QualType T = Context.getBaseElementType(VD->getType());        if (!T->isDependentType()) { -        while (CanQual<ArrayType> AT = T->getAs<ArrayType>()) -          T = AT->getElementType(); -        if (CanQual<RecordType> RT = T->getAs<RecordType>()) -          if (!cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor()) -            OutDiag = diag::note_exits_dtor; +        // C++0x [stmt.dcl]p3: +        //   A program that jumps from a point where a variable with automatic +        //   storage duration is not in scope to a point where it is in scope +        //   is ill-formed unless the variable has scalar type, class type with +        //   a trivial default constructor and a trivial destructor, a  +        //   cv-qualified version of one of these types, or an array of one of +        //   the preceding types and is declared without an initializer (8.5). +        // Check whether this is a C++ class. +        CXXRecordDecl *Record = T->getAsCXXRecordDecl(); +         +        if (const Expr *Init = VD->getInit()) { +          bool CallsTrivialConstructor = false; +          if (Record) { +            // FIXME: With generalized initializer lists, this may +            // classify "X x{};" as having no initializer. +            if (const CXXConstructExpr *Construct  +                                        = dyn_cast<CXXConstructExpr>(Init)) +              if (const CXXConstructorDecl *Constructor +                                                = Construct->getConstructor()) +                if ((Context.getLangOptions().CPlusPlus0x +                       ? Record->hasTrivialDefaultConstructor() +                       : Record->isPOD()) && +                    Constructor->isDefaultConstructor()) +                  CallsTrivialConstructor = true; +          } +           +          if (!CallsTrivialConstructor) +            InDiag = diag::note_protected_by_variable_init; +        } +         +        // Note whether we have a class with a non-trivial destructor. +        if (Record && !Record->hasTrivialDestructor()) +          OutDiag = diag::note_exits_dtor;        }      } diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp index 7707fb1104be..8297b3155a8c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp @@ -31,6 +31,7 @@  #include "clang/AST/DeclCXX.h"  #include "clang/AST/DeclObjC.h"  #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h"  #include "clang/AST/StmtCXX.h"  #include "clang/Lex/Preprocessor.h"  #include "clang/Basic/PartialDiagnostic.h" @@ -377,30 +378,22 @@ void Sema::ActOnEndOfTranslationUnit() {        }      } -    bool SomethingChanged; -    do { -      SomethingChanged = false; -       -      // If DefinedUsedVTables ends up marking any virtual member functions it -      // might lead to more pending template instantiations, which we then need -      // to instantiate. -      if (DefineUsedVTables()) -        SomethingChanged = true; - -      // C++: Perform implicit template instantiations. -      // -      // FIXME: When we perform these implicit instantiations, we do not -      // carefully keep track of the point of instantiation (C++ [temp.point]). -      // This means that name lookup that occurs within the template -      // instantiation will always happen at the end of the translation unit, -      // so it will find some names that should not be found. Although this is -      // common behavior for C++ compilers, it is technically wrong. In the -      // future, we either need to be able to filter the results of name lookup -      // or we need to perform template instantiations earlier. -      if (PerformPendingInstantiations()) -        SomethingChanged = true; -       -    } while (SomethingChanged); +    // If DefinedUsedVTables ends up marking any virtual member functions it +    // might lead to more pending template instantiations, which we then need +    // to instantiate. +    DefineUsedVTables(); + +    // C++: Perform implicit template instantiations. +    // +    // FIXME: When we perform these implicit instantiations, we do not +    // carefully keep track of the point of instantiation (C++ [temp.point]). +    // This means that name lookup that occurs within the template +    // instantiation will always happen at the end of the translation unit, +    // so it will find some names that should not be found. Although this is +    // common behavior for C++ compilers, it is technically wrong. In the +    // future, we either need to be able to filter the results of name lookup +    // or we need to perform template instantiations earlier. +    PerformPendingInstantiations();    }    // Remove file scoped decls that turned out to be used. @@ -473,6 +466,12 @@ void Sema::ActOnEndOfTranslationUnit() {    } +  if (LangOpts.CPlusPlus0x && +      Diags.getDiagnosticLevel(diag::warn_delegating_ctor_cycle, +                               SourceLocation()) +        != Diagnostic::Ignored) +    CheckDelegatingCtorCycles(); +    // If there were errors, disable 'unused' warnings since they will mostly be    // noise.    if (!Diags.hasErrorOccurred()) { @@ -570,9 +569,12 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {        break;      case DiagnosticIDs::SFINAE_AccessControl: -      // Unless access checking is specifically called out as a SFINAE -      // error, report this diagnostic. -      if (!SemaRef.AccessCheckingSFINAE) +      // Per C++ Core Issue 1170, access control is part of SFINAE. +      // Additionally, the AccessCheckingSFINAE flag can be used to temporary +      // make access control a part of SFINAE for the purposes of checking +      // type traits. +      if (!SemaRef.AccessCheckingSFINAE && +          !SemaRef.getLangOptions().CPlusPlus0x)          break;      case DiagnosticIDs::SFINAE_SubstitutionFailure: @@ -763,3 +765,101 @@ void PrettyDeclStackTraceEntry::print(llvm::raw_ostream &OS) const {    OS << '\n';  } + +/// \brief Figure out if an expression could be turned into a call. +/// +/// Use this when trying to recover from an error where the programmer may have +/// written just the name of a function instead of actually calling it. +/// +/// \param E - The expression to examine. +/// \param ZeroArgCallReturnTy - If the expression can be turned into a call +///  with no arguments, this parameter is set to the type returned by such a +///  call; otherwise, it is set to an empty QualType. +/// \param NonTemplateOverloads - If the expression is an overloaded function +///  name, this parameter is populated with the decls of the various overloads. +bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy, +                          UnresolvedSetImpl &NonTemplateOverloads) { +  ZeroArgCallReturnTy = QualType(); +  NonTemplateOverloads.clear(); +  if (const OverloadExpr *Overloads = dyn_cast<OverloadExpr>(&E)) { +    for (OverloadExpr::decls_iterator it = Overloads->decls_begin(), +         DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) { +      // Our overload set may include TemplateDecls, which we'll ignore for our +      // present purpose. +      if (const FunctionDecl *OverloadDecl = dyn_cast<FunctionDecl>(*it)) { +        NonTemplateOverloads.addDecl(*it); +        if (OverloadDecl->getMinRequiredArguments() == 0) +          ZeroArgCallReturnTy = OverloadDecl->getResultType(); +      } +    } +    return true; +  } + +  if (const DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(&E)) { +    if (const FunctionDecl *Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) { +      if (Fun->getMinRequiredArguments() == 0) +        ZeroArgCallReturnTy = Fun->getResultType(); +      return true; +    } +  } + +  // We don't have an expression that's convenient to get a FunctionDecl from, +  // but we can at least check if the type is "function of 0 arguments". +  QualType ExprTy = E.getType(); +  const FunctionType *FunTy = NULL; +  QualType PointeeTy = ExprTy->getPointeeType(); +  if (!PointeeTy.isNull()) +    FunTy = PointeeTy->getAs<FunctionType>(); +  if (!FunTy) +    FunTy = ExprTy->getAs<FunctionType>(); +  if (!FunTy && ExprTy == Context.BoundMemberTy) { +    // Look for the bound-member type.  If it's still overloaded, give up, +    // although we probably should have fallen into the OverloadExpr case above +    // if we actually have an overloaded bound member. +    QualType BoundMemberTy = Expr::findBoundMemberType(&E); +    if (!BoundMemberTy.isNull()) +      FunTy = BoundMemberTy->castAs<FunctionType>(); +  } + +  if (const FunctionProtoType *FPT = +      dyn_cast_or_null<FunctionProtoType>(FunTy)) { +    if (FPT->getNumArgs() == 0) +      ZeroArgCallReturnTy = FunTy->getResultType(); +    return true; +  } +  return false; +} + +/// \brief Give notes for a set of overloads. +/// +/// A companion to isExprCallable. In cases when the name that the programmer +/// wrote was an overloaded function, we may be able to make some guesses about +/// plausible overloads based on their return types; such guesses can be handed +/// off to this method to be emitted as notes. +/// +/// \param Overloads - The overloads to note. +/// \param FinalNoteLoc - If we've suppressed printing some overloads due to +///  -fshow-overloads=best, this is the location to attach to the note about too +///  many candidates. Typically this will be the location of the original +///  ill-formed expression. +void Sema::NoteOverloads(const UnresolvedSetImpl &Overloads, +                         const SourceLocation FinalNoteLoc) { +  int ShownOverloads = 0; +  int SuppressedOverloads = 0; +  for (UnresolvedSetImpl::iterator It = Overloads.begin(), +       DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) { +    // FIXME: Magic number for max shown overloads stolen from +    // OverloadCandidateSet::NoteCandidates. +    if (ShownOverloads >= 4 && +        Diags.getShowOverloads() == Diagnostic::Ovl_Best) { +      ++SuppressedOverloads; +      continue; +    } +    Diag(cast<FunctionDecl>(*It)->getSourceRange().getBegin(), +         diag::note_member_ref_possible_intended_overload); +    ++ShownOverloads; +  } +  if (SuppressedOverloads) +    Diag(FinalNoteLoc, diag::note_ovl_too_many_candidates) +        << SuppressedOverloads; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp index 411d424dd8df..a26737e00e4d 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp @@ -146,8 +146,10 @@ struct AccessTarget : public AccessedEntity {                 MemberNonce _,                 CXXRecordDecl *NamingClass,                 DeclAccessPair FoundDecl, -               QualType BaseObjectType) -    : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType) { +               QualType BaseObjectType, +               bool IsUsingDecl = false) +    : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType), +      IsUsingDeclaration(IsUsingDecl) {      initialize();    } @@ -216,6 +218,7 @@ private:      DeclaringClass = DeclaringClass->getCanonicalDecl();    } +  bool IsUsingDeclaration : 1;    bool HasInstanceContext : 1;    mutable bool CalculatedInstanceContext : 1;    mutable const CXXRecordDecl *InstanceContext; @@ -445,8 +448,8 @@ static AccessResult MatchesFriend(Sema &S,        continue;      // If the template names don't match, it can't be a dependent -    // match.  This isn't true in C++0x because of template aliases. -    if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName()) +    // match. +    if (CTD->getDeclName() != Friend->getDeclName())        continue;      // If the class's context can't instantiate to the friend's @@ -1129,6 +1132,44 @@ static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,    DiagnoseAccessPath(S, EC, Entity);  } +/// MSVC has a bug where if during an using declaration name lookup,  +/// the declaration found is unaccessible (private) and that declaration  +/// was bring into scope via another using declaration whose target +/// declaration is accessible (public) then no error is generated. +/// Example: +///   class A { +///   public: +///     int f(); +///   }; +///   class B : public A { +///   private: +///     using A::f; +///   }; +///   class C : public B { +///   private: +///     using B::f; +///   }; +/// +/// Here, B::f is private so this should fail in Standard C++, but  +/// because B::f refers to A::f which is public MSVC accepts it. +static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S,  +                                                 SourceLocation AccessLoc, +                                                 AccessTarget &Entity) { +  if (UsingShadowDecl *Shadow = +                         dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) { +    const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl(); +    if (Entity.getTargetDecl()->getAccess() == AS_private &&  +        (OrigDecl->getAccess() == AS_public || +         OrigDecl->getAccess() == AS_protected)) { +      S.Diag(AccessLoc, diag::war_ms_using_declaration_inaccessible)  +        << Shadow->getUsingDecl()->getQualifiedNameAsString() +        << OrigDecl->getQualifiedNameAsString(); +      return true; +    } +  } +  return false; +} +  /// Determines whether the accessed entity is accessible.  Public members  /// have been weeded out by this point.  static AccessResult IsAccessible(Sema &S, @@ -1232,6 +1273,10 @@ static AccessResult CheckEffectiveAccess(Sema &S,                                           AccessTarget &Entity) {    assert(Entity.getAccess() != AS_public && "called for public access!"); +  if (S.getLangOptions().Microsoft && +      IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity)) +    return AR_accessible; +    switch (IsAccessible(S, EC, Entity)) {    case AR_dependent:      DelayDependentAccess(S, EC, Loc, Entity); @@ -1415,30 +1460,48 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,    AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,                              DeclAccessPair::make(Constructor, Access),                              QualType()); +  PartialDiagnostic PD(PDiag());    switch (Entity.getKind()) {    default: -    AccessEntity.setDiag(IsCopyBindingRefToTemp -                         ? diag::ext_rvalue_to_reference_access_ctor -                         : diag::err_access_ctor); +    PD = PDiag(IsCopyBindingRefToTemp +                 ? diag::ext_rvalue_to_reference_access_ctor +                 : diag::err_access_ctor); +      break;    case InitializedEntity::EK_Base: -    AccessEntity.setDiag(PDiag(diag::err_access_base) -                          << Entity.isInheritedVirtualBase() -                          << Entity.getBaseSpecifier()->getType() -                          << getSpecialMember(Constructor)); +    PD = PDiag(diag::err_access_base_ctor); +    PD << Entity.isInheritedVirtualBase() +       << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor);      break;    case InitializedEntity::EK_Member: {      const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl()); -    AccessEntity.setDiag(PDiag(diag::err_access_field) -                          << Field->getType() -                          << getSpecialMember(Constructor)); +    PD = PDiag(diag::err_access_field_ctor); +    PD << Field->getType() << getSpecialMember(Constructor);      break;    }    } +  return CheckConstructorAccess(UseLoc, Constructor, Access, PD); +} + +/// Checks access to a constructor. +Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, +                                                CXXConstructorDecl *Constructor, +                                                AccessSpecifier Access, +                                                PartialDiagnostic PD) { +  if (!getLangOptions().AccessControl || +      Access == AS_public) +    return AR_accessible; + +  CXXRecordDecl *NamingClass = Constructor->getParent(); +  AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass, +                            DeclAccessPair::make(Constructor, Access), +                            QualType()); +  AccessEntity.setDiag(PD); +    return CheckAccess(*this, UseLoc, AccessEntity);  } @@ -1465,7 +1528,8 @@ Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,  Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,                                                 SourceRange PlacementRange,                                                 CXXRecordDecl *NamingClass, -                                               DeclAccessPair Found) { +                                               DeclAccessPair Found, +                                               bool Diagnose) {    if (!getLangOptions().AccessControl ||        !NamingClass ||        Found.getAccess() == AS_public) @@ -1473,8 +1537,9 @@ Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,    AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,                        QualType()); -  Entity.setDiag(diag::err_access) -    << PlacementRange; +  if (Diagnose) +    Entity.setDiag(diag::err_access) +      << PlacementRange;    return CheckAccess(*this, OpLoc, Entity);  } @@ -1573,9 +1638,8 @@ void Sema::CheckLookupAccess(const LookupResult &R) {      if (I.getAccess() != AS_public) {        AccessTarget Entity(Context, AccessedEntity::Member,                            R.getNamingClass(), I.getPair(), -                          R.getBaseObjectType()); +                          R.getBaseObjectType(), R.isUsingDeclaration());        Entity.setDiag(diag::err_access); -        CheckAccess(*this, R.getNameLoc(), Entity);      }    } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp index ed54f0f54425..e46ad5bcfeb5 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp @@ -252,8 +252,7 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,                                       (CT == CT_CStyle || CT == CT_Functional));    InitializationSequence sequence(S, entity, initKind, &src, 1); -  assert(sequence.getKind() == InitializationSequence::FailedSequence && -         "initialization succeeded on second try?"); +  assert(sequence.Failed() && "initialization succeeded on second try?");    switch (sequence.getFailureKind()) {    default: return false; @@ -1195,8 +1194,7 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,    // On the other hand, if we're checking a C-style cast, we've still got    // the reinterpret_cast way. -  if (InitSeq.getKind() == InitializationSequence::FailedSequence &&  -    (CStyle || !DestType->isReferenceType())) +  if (InitSeq.Failed() && (CStyle || !DestType->isReferenceType()))      return TC_NotApplicable;    ExprResult Result @@ -1288,6 +1286,62 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,    return TC_Success;  } +// Checks for undefined behavior in reinterpret_cast. +// The cases that is checked for is: +// *reinterpret_cast<T*>(&a) +// reinterpret_cast<T&>(a) +// where accessing 'a' as type 'T' will result in undefined behavior. +void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, +                                          bool IsDereference, +                                          SourceRange Range) { +  unsigned DiagID = IsDereference ? +                        diag::warn_pointer_indirection_from_incompatible_type : +                        diag::warn_undefined_reinterpret_cast; + +  if (Diags.getDiagnosticLevel(DiagID, Range.getBegin()) == +          Diagnostic::Ignored) { +    return; +  } + +  QualType SrcTy, DestTy; +  if (IsDereference) { +    if (!SrcType->getAs<PointerType>() || !DestType->getAs<PointerType>()) { +      return; +    } +    SrcTy = SrcType->getPointeeType(); +    DestTy = DestType->getPointeeType(); +  } else { +    if (!DestType->getAs<ReferenceType>()) { +      return; +    } +    SrcTy = SrcType; +    DestTy = DestType->getPointeeType(); +  } + +  // Cast is compatible if the types are the same. +  if (Context.hasSameUnqualifiedType(DestTy, SrcTy)) { +    return; +  } +  // or one of the types is a char or void type +  if (DestTy->isAnyCharacterType() || DestTy->isVoidType() || +      SrcTy->isAnyCharacterType() || SrcTy->isVoidType()) { +    return; +  } +  // or one of the types is a tag type. +  if (SrcTy->getAs<TagType>() || DestTy->getAs<TagType>()) { +    return; +  } + +  // FIXME: Scoped enums? +  if ((SrcTy->isUnsignedIntegerType() && DestTy->isSignedIntegerType()) || +      (SrcTy->isSignedIntegerType() && DestTy->isUnsignedIntegerType())) { +    if (Context.getTypeSize(DestTy) == Context.getTypeSize(SrcTy)) { +      return; +    } +  } + +  Diag(Range.getBegin(), DiagID) << SrcType << DestType << Range; +}  static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,                                          QualType DestType, bool CStyle, @@ -1324,6 +1378,11 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,        return TC_NotApplicable;      } +    if (!CStyle) { +      Self.CheckCompatibleReinterpretCast(SrcType, DestType, +                                          /*isDereference=*/false, OpRange); +    } +      // C++ 5.2.10p10: [...] a reference cast reinterpret_cast<T&>(x) has the      //   same effect as the conversion *reinterpret_cast<T*>(&x) with the      //   built-in & and * operators. @@ -1454,9 +1513,11 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,    if (DestType->isIntegralType(Self.Context)) {      assert(srcIsPtr && "One type must be a pointer");      // C++ 5.2.10p4: A pointer can be explicitly converted to any integral -    //   type large enough to hold it. -    if (Self.Context.getTypeSize(SrcType) > -        Self.Context.getTypeSize(DestType)) { +    //   type large enough to hold it; except in Microsoft mode, where the +    //   integral type size doesn't matter. +    if ((Self.Context.getTypeSize(SrcType) > +         Self.Context.getTypeSize(DestType)) && +         !Self.getLangOptions().Microsoft) {        msg = diag::err_bad_reinterpret_cast_small_int;        return TC_Failed;      } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp index 7049f6b01d26..61d9e93f2ff5 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -94,9 +94,13 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,      if (EnteringContext) {        const Type *NNSType = NNS->getAsType();        if (!NNSType) { -        // do nothing, fall out -      } else if (const TemplateSpecializationType *SpecType -                   = NNSType->getAs<TemplateSpecializationType>()) { +        return 0; +      } + +      // Look through type alias templates, per C++0x [temp.dep.type]p1. +      NNSType = Context.getCanonicalType(NNSType); +      if (const TemplateSpecializationType *SpecType +            = NNSType->getAs<TemplateSpecializationType>()) {          // We are entering the context of the nested name specifier, so try to          // match the nested name specifier to either a primary class template          // or a class template partial specialization. @@ -382,7 +386,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,      isDependent = ObjectType->isDependentType();    } else if (SS.isSet()) {      // This nested-name-specifier occurs after another nested-name-specifier, -    // so long into the context associated with the prior nested-name-specifier. +    // so look into the context associated with the prior nested-name-specifier.      LookupCtx = computeDeclContext(SS, EnteringContext);      isDependent = isDependentScopeSpecifier(SS);      Found.setContextRange(SS.getRange()); @@ -419,7 +423,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,        //   class-name or namespace-name. [...]        //        // Qualified name lookup into a class will not find a namespace-name, -      // so we do not need to diagnoste that case specifically. However, +      // so we do not need to diagnose that case specifically. However,        // this qualified name lookup may find nothing. In that case, perform        // unqualified name lookup in the given scope (if available) or        // reconstruct the result from when name lookup was performed at template @@ -546,25 +550,33 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,        InjectedClassNameTypeLoc InjectedTL          = TLB.push<InjectedClassNameTypeLoc>(T);        InjectedTL.setNameLoc(IdentifierLoc); -    } else if (isa<RecordDecl>(SD)) { +    } else if (isa<RecordType>(T)) {        RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T);        RecordTL.setNameLoc(IdentifierLoc); -    } else if (isa<TypedefNameDecl>(SD)) { +    } else if (isa<TypedefType>(T)) {        TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T);        TypedefTL.setNameLoc(IdentifierLoc); -    } else if (isa<EnumDecl>(SD)) { +    } else if (isa<EnumType>(T)) {        EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T);        EnumTL.setNameLoc(IdentifierLoc); -    } else if (isa<TemplateTypeParmDecl>(SD)) { +    } else if (isa<TemplateTypeParmType>(T)) {        TemplateTypeParmTypeLoc TemplateTypeTL          = TLB.push<TemplateTypeParmTypeLoc>(T);        TemplateTypeTL.setNameLoc(IdentifierLoc); -    } else { -      assert(isa<UnresolvedUsingTypenameDecl>(SD) &&  -             "Unhandled TypeDecl node in nested-name-specifier"); +    } else if (isa<UnresolvedUsingType>(T)) {        UnresolvedUsingTypeLoc UnresolvedTL          = TLB.push<UnresolvedUsingTypeLoc>(T);        UnresolvedTL.setNameLoc(IdentifierLoc); +    } else if (isa<SubstTemplateTypeParmType>(T)) { +      SubstTemplateTypeParmTypeLoc TL  +        = TLB.push<SubstTemplateTypeParmTypeLoc>(T); +      TL.setNameLoc(IdentifierLoc); +    } else if (isa<SubstTemplateTypeParmPackType>(T)) { +      SubstTemplateTypeParmPackTypeLoc TL +        = TLB.push<SubstTemplateTypeParmPackTypeLoc>(T); +      TL.setNameLoc(IdentifierLoc); +    } else { +      llvm_unreachable("Unhandled TypeDecl node in nested-name-specifier");      }      SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T), @@ -704,8 +716,13 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,    if (T.isNull())      return true; -  // FIXME: Template aliases will need to check the resulting type to make -  // sure that it's either dependent or a tag type. +  // Alias template specializations can produce types which are not valid +  // nested name specifiers. +  if (!T->isDependentType() && !T->getAs<TagType>()) { +    Diag(TemplateNameLoc, diag::err_nested_name_spec_non_tag) << T; +    NoteAllFoundTemplates(Template.get()); +    return true; +  }    // Provide source-location information for the template specialization     // type. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp index 5b645df8d293..7e22b33fd6bf 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp @@ -318,9 +318,13 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {                            TheCall->getCallee()->getLocStart());    } -  // Memset handling -  if (FnInfo->isStr("memset")) -    CheckMemsetArguments(TheCall); +  // Memset/memcpy/memmove handling +  if (FDecl->getLinkage() == ExternalLinkage && +      (!getLangOptions().CPlusPlus || FDecl->isExternC())) { +    if (FnInfo->isStr("memset") || FnInfo->isStr("memcpy") ||  +        FnInfo->isStr("memmove")) +      CheckMemsetcpymoveArguments(TheCall, FnInfo); +  }    return false;  } @@ -1832,49 +1836,59 @@ void Sema::CheckFormatString(const StringLiteral *FExpr,  //===--- CHECK: Standard memory functions ---------------------------------===// +/// \brief Determine whether the given type is a dynamic class type (e.g., +/// whether it has a vtable). +static bool isDynamicClassType(QualType T) { +  if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) +    if (CXXRecordDecl *Definition = Record->getDefinition()) +      if (Definition->isDynamicClass()) +        return true; +   +  return false; +} +  /// \brief Check for dangerous or invalid arguments to memset().  /// -/// This issues warnings on known problematic or dangerous or unspecified -/// arguments to the standard 'memset' function call. +/// This issues warnings on known problematic, dangerous or unspecified +/// arguments to the standard 'memset', 'memcpy', and 'memmove' function calls.  ///  /// \param Call The call expression to diagnose. -void Sema::CheckMemsetArguments(const CallExpr *Call) { +void Sema::CheckMemsetcpymoveArguments(const CallExpr *Call, +                                       const IdentifierInfo *FnName) {    // It is possible to have a non-standard definition of memset.  Validate    // we have the proper number of arguments, and if not, abort further    // checking.    if (Call->getNumArgs() != 3)      return; -  const Expr *Dest = Call->getArg(0)->IgnoreParenImpCasts(); - -  // The type checking for this warning is moderately expensive, only do it -  // when enabled. -  if (getDiagnostics().getDiagnosticLevel(diag::warn_non_pod_memset, -                                          Dest->getExprLoc()) == -      Diagnostic::Ignored) -    return; - -  QualType DestTy = Dest->getType(); -  if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) { -    QualType PointeeTy = DestPtrTy->getPointeeType(); -    if (PointeeTy->isVoidType()) -      return; - -    // Check the C++11 POD definition regardless of language mode; it is more -    // relaxed than earlier definitions and we don't want spurrious warnings. -    if (PointeeTy->isCXX11PODType()) -      return; - -    DiagRuntimeBehavior( -      Dest->getExprLoc(), Dest, -      PDiag(diag::warn_non_pod_memset) -        << PointeeTy << Call->getCallee()->getSourceRange()); +  unsigned LastArg = FnName->isStr("memset")? 1 : 2; +  for (unsigned ArgIdx = 0; ArgIdx != LastArg; ++ArgIdx) { +    const Expr *Dest = Call->getArg(ArgIdx)->IgnoreParenImpCasts(); + +    QualType DestTy = Dest->getType(); +    if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) { +      QualType PointeeTy = DestPtrTy->getPointeeType(); +      if (PointeeTy->isVoidType()) +        continue; + +      // Always complain about dynamic classes. +      if (isDynamicClassType(PointeeTy)) { +        DiagRuntimeBehavior( +          Dest->getExprLoc(), Dest, +          PDiag(diag::warn_dyn_class_memaccess) +            << ArgIdx << FnName << PointeeTy  +            << Call->getCallee()->getSourceRange()); +      } else { +        continue; +      } -    SourceRange ArgRange = Call->getArg(0)->getSourceRange(); -    DiagRuntimeBehavior( -      Dest->getExprLoc(), Dest, -      PDiag(diag::note_non_pod_memset_silence) -        << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)")); +      SourceRange ArgRange = Call->getArg(0)->getSourceRange(); +      DiagRuntimeBehavior( +        Dest->getExprLoc(), Dest, +        PDiag(diag::note_bad_memaccess_silence) +          << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)")); +      break; +    }    }  } @@ -2391,7 +2405,7 @@ IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty,    // the sign right on this one case.  It would be nice if APValue    // preserved this.    assert(result.isLValue()); -  return IntRange(MaxWidth, Ty->isUnsignedIntegerType()); +  return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType());  }  /// Pseudo-evaluate the given integer expression, estimating the @@ -2565,7 +2579,8 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {      llvm::APSInt BitWidthAP = BitField->getBitWidth()->EvaluateAsInt(C);      unsigned BitWidth = BitWidthAP.getZExtValue(); -    return IntRange(BitWidth, BitField->getType()->isUnsignedIntegerType()); +    return IntRange(BitWidth,  +                    BitField->getType()->isUnsignedIntegerOrEnumerationType());    }    return IntRange::forValueOfType(C, E->getType()); @@ -2982,6 +2997,13 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,    if (!Source->isIntegerType() || !Target->isIntegerType())      return; +  if ((E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) +           == Expr::NPCK_GNUNull) && Target->isIntegerType()) { +    S.Diag(E->getExprLoc(), diag::warn_impcast_null_pointer_to_integer) +        << E->getSourceRange() << clang::SourceRange(CC); +    return; +  } +    IntRange SourceRange = GetExprRange(S.Context, E);    IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp index cc8726de9df8..e328eeb0aa2b 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp @@ -2658,6 +2658,16 @@ CXCursorKind clang::getCursorKindForDecl(Decl *D) {      case Decl::UnresolvedUsingTypename:         return CXCursor_UsingDeclaration; +    case Decl::ObjCPropertyImpl: +      switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) { +      case ObjCPropertyImplDecl::Dynamic: +        return CXCursor_ObjCDynamicDecl; +           +      case ObjCPropertyImplDecl::Synthesize: +        return CXCursor_ObjCSynthesizeDecl; +      } +      break; +            default:        if (TagDecl *TD = dyn_cast<TagDecl>(D)) {          switch (TD->getTagKind()) { @@ -3078,6 +3088,7 @@ typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;  static void AddObjCProperties(ObjCContainerDecl *Container,                                 bool AllowCategories, +                              bool AllowNullaryMethods,                                DeclContext *CurContext,                                AddedPropertiesSet &AddedProperties,                                ResultBuilder &Results) { @@ -3092,32 +3103,75 @@ static void AddObjCProperties(ObjCContainerDecl *Container,        Results.MaybeAddResult(Result(*P, 0), CurContext);    } +  // Add nullary methods +  if (AllowNullaryMethods) { +    ASTContext &Context = Container->getASTContext(); +    for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), +                                         MEnd = Container->meth_end(); +         M != MEnd; ++M) { +      if (M->getSelector().isUnarySelector()) +        if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0)) +          if (AddedProperties.insert(Name)) { +            CodeCompletionBuilder Builder(Results.getAllocator()); +            AddResultTypeChunk(Context, *M, Builder); +            Builder.AddTypedTextChunk( +                            Results.getAllocator().CopyString(Name->getName())); +             +            CXAvailabilityKind Availability = CXAvailability_Available; +            switch (M->getAvailability()) { +            case AR_Available: +            case AR_NotYetIntroduced: +              Availability = CXAvailability_Available;       +              break; +               +            case AR_Deprecated: +              Availability = CXAvailability_Deprecated; +              break; +               +            case AR_Unavailable: +              Availability = CXAvailability_NotAvailable; +              break; +            } + +            Results.MaybeAddResult(Result(Builder.TakeString(), +                                  CCP_MemberDeclaration + CCD_MethodAsProperty, +                                          M->isInstanceMethod() +                                            ? CXCursor_ObjCInstanceMethodDecl +                                            : CXCursor_ObjCClassMethodDecl, +                                          Availability), +                                          CurContext); +          } +    } +  } +     +      // Add properties in referenced protocols.    if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {      for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),                                            PEnd = Protocol->protocol_end();           P != PEnd; ++P) -      AddObjCProperties(*P, AllowCategories, CurContext, AddedProperties,  -                        Results); +      AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,  +                        AddedProperties, Results);    } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){      if (AllowCategories) {        // Look through categories.        for (ObjCCategoryDecl *Category = IFace->getCategoryList();             Category; Category = Category->getNextClassCategory()) -        AddObjCProperties(Category, AllowCategories, CurContext,  -                          AddedProperties, Results); +        AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,  +                          CurContext, AddedProperties, Results);      }      // Look through protocols.      for (ObjCInterfaceDecl::all_protocol_iterator           I = IFace->all_referenced_protocol_begin(),           E = IFace->all_referenced_protocol_end(); I != E; ++I) -      AddObjCProperties(*I, AllowCategories, CurContext, AddedProperties, -                        Results); +      AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext, +                        AddedProperties, Results);      // Look in the superclass.      if (IFace->getSuperClass()) -      AddObjCProperties(IFace->getSuperClass(), AllowCategories, CurContext,  +      AddObjCProperties(IFace->getSuperClass(), AllowCategories,  +                        AllowNullaryMethods, CurContext,                           AddedProperties, Results);    } else if (const ObjCCategoryDecl *Category                                      = dyn_cast<ObjCCategoryDecl>(Container)) { @@ -3125,8 +3179,8 @@ static void AddObjCProperties(ObjCContainerDecl *Container,      for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),                                            PEnd = Category->protocol_end();            P != PEnd; ++P) -      AddObjCProperties(*P, AllowCategories, CurContext, AddedProperties, -                        Results); +      AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext, +                        AddedProperties, Results);    }  } @@ -3192,14 +3246,16 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,      const ObjCObjectPointerType *ObjCPtr        = BaseType->getAsObjCInterfacePointerType();      assert(ObjCPtr && "Non-NULL pointer guaranteed above!"); -    AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, CurContext,  +    AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,  +                      /*AllowNullaryMethods=*/true, CurContext,                         AddedProperties, Results);      // Add properties from the protocols in a qualified interface.      for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),                                                E = ObjCPtr->qual_end();           I != E; ++I) -      AddObjCProperties(*I, true, CurContext, AddedProperties, Results); +      AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,  +                        AddedProperties, Results);    } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||               (!IsArrow && BaseType->isObjCObjectType())) {      // Objective-C instance variable access. @@ -4109,6 +4165,8 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {      Results.AddResult(CodeCompletionResult("copy"));    if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))      Results.AddResult(CodeCompletionResult("nonatomic")); +  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic)) +    Results.AddResult(CodeCompletionResult("atomic"));    if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {      CodeCompletionBuilder Setter(Results.getAllocator());      Setter.AddTypedTextChunk("setter"); @@ -5334,11 +5392,13 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl) {    Results.EnterNewScope();    if (ObjCImplementationDecl *ClassImpl          = dyn_cast<ObjCImplementationDecl>(Container)) -    AddObjCProperties(ClassImpl->getClassInterface(), false, CurContext,  +    AddObjCProperties(ClassImpl->getClassInterface(), false,  +                      /*AllowNullaryMethods=*/false, CurContext,                         AddedProperties, Results);    else      AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(), -                      false, CurContext, AddedProperties, Results); +                      false, /*AllowNullaryMethods=*/false, CurContext,  +                      AddedProperties, Results);    Results.ExitScope();    HandleCodeCompleteResults(this, CodeCompleter,  @@ -5549,7 +5609,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,                                         bool IsInstanceMethod,                                         QualType ReturnType,                                         ASTContext &Context, -                                       const KnownMethodsMap &KnownMethods, +                                       VisitedSelectorSet &KnownSelectors,                                         ResultBuilder &Results) {    IdentifierInfo *PropName = Property->getIdentifier();    if (!PropName || PropName->getLength() == 0) @@ -5595,7 +5655,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,    // Add the normal accessor -(type)key.    if (IsInstanceMethod && -      !KnownMethods.count(Selectors.getNullarySelector(PropName)) && +      KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&        ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {      if (ReturnType.isNull())        AddObjCPassingTypeChunk(Property->getType(), Context, Builder); @@ -5615,7 +5675,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,           Property->getType()->isBooleanType())))) {      std::string SelectorName = (llvm::Twine("is") + UpperKey).str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); -    if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("BOOL"); @@ -5634,7 +5694,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,        !Property->getSetterMethodDecl()) {      std::string SelectorName = (llvm::Twine("set") + UpperKey).str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); -    if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("void"); @@ -5685,7 +5745,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,        (ReturnType.isNull() || ReturnType->isIntegerType())) {      std::string SelectorName = (llvm::Twine("countOf") + UpperKey).str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); -    if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("NSUInteger"); @@ -5708,7 +5768,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,      std::string SelectorName        = (llvm::Twine("objectIn") + UpperKey + "AtIndex").str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); -    if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("id"); @@ -5735,7 +5795,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,      std::string SelectorName        = (llvm::Twine(Property->getName()) + "AtIndexes").str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); -    if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("NSArray *"); @@ -5760,7 +5820,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,        &Context.Idents.get("range")      }; -    if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) { +    if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("void"); @@ -5794,7 +5854,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,        &Context.Idents.get(SelectorName)      }; -    if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) { +    if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("void"); @@ -5826,7 +5886,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,        &Context.Idents.get("atIndexes")      }; -    if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) { +    if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("void"); @@ -5854,7 +5914,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,      std::string SelectorName        = (llvm::Twine("removeObjectFrom") + UpperKey + "AtIndex").str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);         -    if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("void"); @@ -5876,7 +5936,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,      std::string SelectorName        = (llvm::Twine("remove") + UpperKey + "AtIndexes").str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);         -    if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("void"); @@ -5902,7 +5962,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,        &Context.Idents.get("withObject")      }; -    if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) { +    if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("void"); @@ -5935,7 +5995,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,        &Context.Idents.get(SelectorName2)      }; -    if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) { +    if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("void"); @@ -5968,7 +6028,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,            ->getName() == "NSEnumerator"))) {      std::string SelectorName = (llvm::Twine("enumeratorOf") + UpperKey).str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); -    if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("NSEnumerator *"); @@ -5986,7 +6046,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,        (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {      std::string SelectorName = (llvm::Twine("memberOf") + UpperKey).str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); -    if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddPlaceholderChunk("object-type"); @@ -6016,7 +6076,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,      std::string SelectorName        = (llvm::Twine("add") + UpperKey + llvm::Twine("Object")).str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); -    if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("void"); @@ -6038,7 +6098,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,    if (IsInstanceMethod && ReturnTypeMatchesVoid) {      std::string SelectorName = (llvm::Twine("add") + UpperKey).str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); -    if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("void"); @@ -6060,7 +6120,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,      std::string SelectorName        = (llvm::Twine("remove") + UpperKey + llvm::Twine("Object")).str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); -    if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("void"); @@ -6082,7 +6142,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,    if (IsInstanceMethod && ReturnTypeMatchesVoid) {      std::string SelectorName = (llvm::Twine("remove") + UpperKey).str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); -    if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("void"); @@ -6103,7 +6163,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,    if (IsInstanceMethod && ReturnTypeMatchesVoid) {      std::string SelectorName = (llvm::Twine("intersect") + UpperKey).str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); -    if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("void"); @@ -6131,7 +6191,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,      std::string SelectorName         = (llvm::Twine("keyPathsForValuesAffecting") + UpperKey).str();      IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); -    if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) { +    if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {        if (ReturnType.isNull()) {          Builder.AddChunk(CodeCompletionString::CK_LeftParen);          Builder.AddTextChunk("NSSet *"); @@ -6140,7 +6200,28 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,        Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));        Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,  -                              CXCursor_ObjCInstanceMethodDecl)); +                              CXCursor_ObjCClassMethodDecl)); +    } +  } + +  // + (BOOL)automaticallyNotifiesObserversForKey +  if (!IsInstanceMethod && +      (ReturnType.isNull() || +       ReturnType->isIntegerType() ||  +       ReturnType->isBooleanType())) { +    std::string SelectorName  +      = (llvm::Twine("automaticallyNotifiesObserversOf") + UpperKey).str(); +    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); +    if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { +      if (ReturnType.isNull()) { +        Builder.AddChunk(CodeCompletionString::CK_LeftParen); +        Builder.AddTextChunk("BOOL"); +        Builder.AddChunk(CodeCompletionString::CK_RightParen); +      } +        +      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); +      Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,  +                              CXCursor_ObjCClassMethodDecl));      }    }  } @@ -6271,6 +6352,13 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,      llvm::SmallVector<ObjCContainerDecl *, 4> Containers;      Containers.push_back(SearchDecl); +    VisitedSelectorSet KnownSelectors; +    for (KnownMethodsMap::iterator M = KnownMethods.begin(),  +                                MEnd = KnownMethods.end(); +         M != MEnd; ++M) +      KnownSelectors.insert(M->first); + +          ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);      if (!IFace)        if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl)) @@ -6287,7 +6375,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,                                           PEnd = Containers[I]->prop_end();              P != PEnd; ++P) {          AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,  -                                   KnownMethods, Results); +                                   KnownSelectors, Results);        }      }    } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp index 7214988bdafc..9446c0e8c03f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -891,19 +891,19 @@ static bool isOutOfScopePreviousDeclaration(NamedDecl *,  /// Filters out lookup results that don't fall within the given scope  /// as determined by isDeclInScope. -static void FilterLookupForScope(Sema &SemaRef, LookupResult &R, -                                 DeclContext *Ctx, Scope *S, -                                 bool ConsiderLinkage, -                                 bool ExplicitInstantiationOrSpecialization) { +void Sema::FilterLookupForScope(LookupResult &R, +                                DeclContext *Ctx, Scope *S, +                                bool ConsiderLinkage, +                                bool ExplicitInstantiationOrSpecialization) {    LookupResult::Filter F = R.makeFilter();    while (F.hasNext()) {      NamedDecl *D = F.next(); -    if (SemaRef.isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization)) +    if (isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization))        continue;      if (ConsiderLinkage && -        isOutOfScopePreviousDeclaration(D, Ctx, SemaRef.Context)) +        isOutOfScopePreviousDeclaration(D, Ctx, Context))        continue;      F.erase(); @@ -938,7 +938,7 @@ static void RemoveUsingDecls(LookupResult &R) {  static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) {    // FIXME: Should check for private access too but access is set after we get    // the decl here. -  if (D->isThisDeclarationADefinition()) +  if (D->doesThisDeclarationHaveABody())      return false;    if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D)) @@ -973,10 +973,9 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {          return false;      } -    if (FD->isThisDeclarationADefinition() && +    if (FD->doesThisDeclarationHaveABody() &&          Context.DeclMustBeEmitted(FD))        return false; -    } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {      if (!VD->isFileVarDecl() ||          VD->getType().isConstant(Context) || @@ -1506,18 +1505,21 @@ struct GNUCompatibleParamWarning {  /// getSpecialMember - get the special member enum for a method.  Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) {    if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) { +    if (Ctor->isDefaultConstructor()) +      return Sema::CXXDefaultConstructor; +      if (Ctor->isCopyConstructor())        return Sema::CXXCopyConstructor; -     -    return Sema::CXXConstructor; -  }  -   -  if (isa<CXXDestructorDecl>(MD)) + +    if (Ctor->isMoveConstructor()) +      return Sema::CXXMoveConstructor; +  } else if (isa<CXXDestructorDecl>(MD)) {      return Sema::CXXDestructor; -   -  assert(MD->isCopyAssignmentOperator() &&  -         "Must have copy assignment operator"); -  return Sema::CXXCopyAssignment; +  } else if (MD->isCopyAssignmentOperator()) { +    return Sema::CXXCopyAssignment; +  } + +  return Sema::CXXInvalid;  }  /// canRedefineFunction - checks if a function can be redefined. Currently, @@ -1525,7 +1527,7 @@ Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) {  /// GNU89 mode.  static bool canRedefineFunction(const FunctionDecl *FD,                                  const LangOptions& LangOpts) { -  return (LangOpts.GNUMode && !LangOpts.C99 && !LangOpts.CPlusPlus && +  return (LangOpts.GNUInline && !LangOpts.CPlusPlus &&            FD->isInlineSpecified() &&            FD->getStorageClass() == SC_Extern);  } @@ -1728,6 +1730,11 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {              << New << getSpecialMember(OldMethod);            return true;          } +      } else if (OldMethod->isExplicitlyDefaulted()) { +        Diag(NewMethod->getLocation(), +             diag::err_definition_of_explicitly_defaulted_member) +          << getSpecialMember(OldMethod); +        return true;        }      } @@ -1907,10 +1914,6 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {    if (Old->isPure())      New->setPure(); -  // Merge the "deleted" flag. -  if (Old->isDeleted()) -    New->setDeleted(); -    // Merge attributes from the parameters.  These can mismatch with K&R    // declarations.    if (New->getNumParams() == Old->getNumParams()) @@ -1933,7 +1936,9 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,    for (ObjCMethodDecl::param_iterator oi = oldMethod->param_begin(),           ni = newMethod->param_begin(), ne = newMethod->param_end();         ni != ne; ++ni, ++oi) -    mergeParamDeclAttributes(*ni, *oi, Context);     +    mergeParamDeclAttributes(*ni, *oi, Context); +   +  CheckObjCMethodOverride(newMethod, oldMethod, true);  }  /// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and @@ -2132,6 +2137,16 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {  /// no declarator (e.g. "struct foo;") is parsed.  Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,                                         DeclSpec &DS) { +  return ParsedFreeStandingDeclSpec(S, AS, DS, +                                    MultiTemplateParamsArg(*this, 0, 0)); +} + +/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with +/// no declarator (e.g. "struct foo;") is parsed. It also accopts template +/// parameters to cope with template friend declarations. +Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, +                                       DeclSpec &DS, +                                       MultiTemplateParamsArg TemplateParams) {    Decl *TagD = 0;    TagDecl *Tag = 0;    if (DS.getTypeSpecType() == DeclSpec::TST_class || @@ -2163,7 +2178,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,      // whatever routines created it handled the friendship aspect.      if (TagD && !Tag)        return 0; -    return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0)); +    return ActOnFriendTypeDecl(S, DS, TemplateParams);    }    // Track whether we warned about the fact that there aren't any @@ -2484,6 +2499,24 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,                               PrevSpec, DiagID, getLangOptions());      } +    // Ignore const/volatile/restrict qualifiers. +    if (DS.getTypeQualifiers()) { +      if (DS.getTypeQualifiers() & DeclSpec::TQ_const) +        Diag(DS.getConstSpecLoc(), diag::ext_anonymous_struct_union_qualified) +          << Record->isUnion() << 0  +          << FixItHint::CreateRemoval(DS.getConstSpecLoc()); +      if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) +        Diag(DS.getVolatileSpecLoc(), diag::ext_anonymous_struct_union_qualified) +          << Record->isUnion() << 1 +          << FixItHint::CreateRemoval(DS.getVolatileSpecLoc()); +      if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) +        Diag(DS.getRestrictSpecLoc(), diag::ext_anonymous_struct_union_qualified) +          << Record->isUnion() << 2  +          << FixItHint::CreateRemoval(DS.getRestrictSpecLoc()); + +      DS.ClearTypeQualifiers(); +    } +      // C++ [class.union]p2:      //   The member-specification of an anonymous union shall only      //   define non-static data members. [Note: nested types and @@ -2502,7 +2535,12 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,            Invalid = true;          } -        if (CheckNontrivialField(FD)) +        // C++ [class.union]p1 +        //   An object of a class with a non-trivial constructor, a non-trivial +        //   copy constructor, a non-trivial destructor, or a non-trivial copy +        //   assignment operator cannot be a member of a union, nor can an +        //   array of such objects. +        if (!getLangOptions().CPlusPlus0x && CheckNontrivialField(FD))            Invalid = true;        } else if ((*Mem)->isImplicit()) {          // Any implicit members are fine. @@ -2572,7 +2610,8 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,                               /*IdentifierInfo=*/0,                               Context.getTypeDeclType(Record),                               TInfo, -                             /*BitWidth=*/0, /*Mutable=*/false); +                             /*BitWidth=*/0, /*Mutable=*/false, +                             /*HasInit=*/false);      Anon->setAccess(AS);      if (getLangOptions().CPlusPlus)        FieldCollector->Add(cast<FieldDecl>(Anon)); @@ -2662,7 +2701,8 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,                               /*IdentifierInfo=*/0,                               Context.getTypeDeclType(Record),                               TInfo, -                             /*BitWidth=*/0, /*Mutable=*/false); +                             /*BitWidth=*/0, /*Mutable=*/false, +                             /*HasInit=*/false);    Anon->setImplicit();    // Add the anonymous struct object to the current context. @@ -2829,7 +2869,8 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,    switch (DS.getTypeSpecType()) {    case DeclSpec::TST_typename:    case DeclSpec::TST_typeofType: -  case DeclSpec::TST_decltype: { +  case DeclSpec::TST_decltype: +  case DeclSpec::TST_underlyingType: {      // Grab the type from the parser.      TypeSourceInfo *TSI = 0;      QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI); @@ -2883,8 +2924,10 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,    return false;  } -Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { -  return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false); +Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D, +                            bool IsFunctionDefinition) { +  return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), +                          IsFunctionDefinition);  }  /// DiagnoseClassNameShadow - Implement C++ [class.mem]p13: @@ -2952,7 +2995,6 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,          << D.getCXXScopeSpec().getRange();        return 0;      } -      bool IsDependentContext = DC->isDependentContext();      if (!IsDependentContext &&  @@ -3294,15 +3336,13 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,    // Handle attributes prior to checking for duplicates in MergeVarDecl    ProcessDeclAttributes(S, NewTD, D); +  CheckTypedefForVariablyModifiedType(S, NewTD); +    return ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration);  } -/// ActOnTypedefNameDecl - Perform semantic checking for a declaration which -/// declares a typedef-name, either using the 'typedef' type specifier or via -/// a C++0x [dcl.typedef]p2 alias-declaration: 'using T = A;'. -NamedDecl* -Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, -                           LookupResult &Previous, bool &Redeclaration) { +void +Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) {    // C99 6.7.7p2: If a typedef name specifies a variably modified type    // then it shall have block scope.    // Note that variably modified types must be fixed before merging the decl so @@ -3333,10 +3373,18 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,        }      }    } +} + +/// ActOnTypedefNameDecl - Perform semantic checking for a declaration which +/// declares a typedef-name, either using the 'typedef' type specifier or via +/// a C++0x [dcl.typedef]p2 alias-declaration: 'using T = A;'. +NamedDecl* +Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, +                           LookupResult &Previous, bool &Redeclaration) {    // Merge the decl with the existing one if appropriate. If the decl is    // in an outer scope, it isn't the same thing. -  FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false, +  FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/ false,                         /*ExplicitInstantiationOrSpecialization=*/false);    if (!Previous.empty()) {      Redeclaration = true; @@ -3518,7 +3566,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,      bool Invalid = false;      if (TemplateParameterList *TemplateParams          = MatchTemplateParametersToScopeSpecifier( -                                                  D.getDeclSpec().getSourceRange().getBegin(), +                                  D.getDeclSpec().getSourceRange().getBegin(), +                                                  D.getIdentifierLoc(),                                                    D.getCXXScopeSpec(),                                                    TemplateParamLists.get(),                                                    TemplateParamLists.size(), @@ -3540,7 +3589,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,            << II            << SourceRange(TemplateParams->getTemplateLoc(),                           TemplateParams->getRAngleLoc()); -        isExplicitSpecialization = true;        }      } @@ -3615,7 +3663,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,    // Don't consider existing declarations that are in a different    // scope and are out-of-semantic-context declarations (if the new    // declaration has linkage). -  FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage(), +  FilterLookupForScope(Previous, DC, S, NewVD->hasLinkage(),                         isExplicitSpecialization);    if (!getLangOptions().CPlusPlus) @@ -3806,8 +3854,12 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD,    }    if (NewVD->hasLocalStorage() && T.isObjCGCWeak() -      && !NewVD->hasAttr<BlocksAttr>()) -    Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local); +      && !NewVD->hasAttr<BlocksAttr>()) { +    if (getLangOptions().getGCMode() != LangOptions::NonGC) +      Diag(NewVD->getLocation(), diag::warn_gc_attribute_weak_on_local); +    else +      Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local); +  }    bool isVM = T->isVariablyModifiedType();    if (isVM || NewVD->hasAttr<CleanupAttr>() || @@ -4062,7 +4114,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,      // Set the lexical context.      NewFD->setLexicalDeclContext(CurContext);      // Filter out previous declarations that don't match the scope. -    FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage(), +    FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(),                           /*ExplicitInstantiationOrSpecialization=*/false);    } else {      isFriend = D.getDeclSpec().isFriendSpecified(); @@ -4088,24 +4140,38 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,        R = CheckConstructorDeclarator(D, R, SC);        // Create the new declaration -      NewFD = CXXConstructorDecl::Create(Context, +      CXXConstructorDecl *NewCD = CXXConstructorDecl::Create( +                                         Context,                                           cast<CXXRecordDecl>(DC),                                           D.getSourceRange().getBegin(),                                           NameInfo, R, TInfo,                                           isExplicit, isInline,                                           /*isImplicitlyDeclared=*/false); + +      NewFD = NewCD;      } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {        // This is a C++ destructor declaration.        if (DC->isRecord()) {          R = CheckDestructorDeclarator(D, R, SC); +        CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); -        NewFD = CXXDestructorDecl::Create(Context, -                                          cast<CXXRecordDecl>(DC), +        CXXDestructorDecl *NewDD = CXXDestructorDecl::Create(Context, Record,                                            D.getSourceRange().getBegin(),                                            NameInfo, R, TInfo,                                            isInline,                                            /*isImplicitlyDeclared=*/false); +        NewFD = NewDD;          isVirtualOkay = true; + +        // If the class is complete, then we now create the implicit exception +        // specification. If the class is incomplete or dependent, we can't do +        // it yet. +        if (getLangOptions().CPlusPlus0x && !Record->isDependentType() && +            Record->getDefinition() && !Record->isBeingDefined() && +            R->getAs<FunctionProtoType>()->getExceptionSpecType() == EST_None) { +          AdjustDestructorExceptionSpec(Record, NewDD); +        } +        } else {          Diag(D.getIdentifierLoc(), diag::err_destructor_not_member); @@ -4162,11 +4228,13 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,          isStatic = true;        // This is a C++ method declaration. -      NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC), -                                    D.getSourceRange().getBegin(), -                                    NameInfo, R, TInfo, -                                    isStatic, SCAsWritten, isInline, -                                    SourceLocation()); +      CXXMethodDecl *NewMD = CXXMethodDecl::Create( +                                               Context, cast<CXXRecordDecl>(DC), +                                               D.getSourceRange().getBegin(), +                                               NameInfo, R, TInfo, +                                               isStatic, SCAsWritten, isInline, +                                               SourceLocation()); +      NewFD = NewMD;        isVirtualOkay = !isStatic;      } else { @@ -4202,6 +4270,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,      if (TemplateParameterList *TemplateParams            = MatchTemplateParametersToScopeSpecifier(                                    D.getDeclSpec().getSourceRange().getBegin(), +                                  D.getIdentifierLoc(),                                    D.getCXXScopeSpec(),                                    TemplateParamLists.get(),                                    TemplateParamLists.size(), @@ -4339,7 +4408,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,      }      // Filter out previous declarations that don't match the scope. -    FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage(), +    FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(),                           isExplicitSpecialization ||                            isFunctionTemplateSpecialization); @@ -4406,6 +4475,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,          bool IsTypeAlias = false;          if (const TypedefType *TT = Param->getType()->getAs<TypedefType>())            IsTypeAlias = isa<TypeAliasDecl>(TT->getDecl()); +        else if (const TemplateSpecializationType *TST = +                   Param->getType()->getAs<TemplateSpecializationType>()) +          IsTypeAlias = TST->isTypeAlias();          Diag(Param->getLocation(), diag::err_param_typedef_of_void)            << IsTypeAlias;        } @@ -4452,8 +4524,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,    if (!getLangOptions().CPlusPlus) {      // Perform semantic checking on the function declaration. -    bool isExplctSpecialization=false; -    CheckFunctionDeclaration(S, NewFD, Previous, isExplctSpecialization, +    bool isExplicitSpecialization=false; +    CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization,                               Redeclaration);      assert((NewFD->isInvalidDecl() || !Redeclaration ||              Previous.getResultKind() != LookupResult::FoundOverloaded) && @@ -4476,7 +4548,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,        HasExplicitTemplateArgs = true; -      if (FunctionTemplate) { +      if (NewFD->isInvalidDecl()) { +        HasExplicitTemplateArgs = false; +      } else if (FunctionTemplate) {          // Function template with explicit template arguments.          Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec)            << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc); @@ -4532,6 +4606,16 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,                                    (HasExplicitTemplateArgs ? &TemplateArgs : 0),                                                       Previous))          NewFD->setInvalidDecl(); +       +      // C++ [dcl.stc]p1: +      //   A storage-class-specifier shall not be specified in an explicit +      //   specialization (14.7.3) +      if (SC != SC_None) { +        Diag(NewFD->getLocation(),  +             diag::err_explicit_specialization_storage_class) +          << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); +      } +            } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD)) {        if (CheckMemberSpecialization(NewFD, Previous))            NewFD->setInvalidDecl(); @@ -4647,8 +4731,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,          << D.getCXXScopeSpec().getRange();      }    } -   -   +  +     // Handle attributes. We need to have merged decls when handling attributes    // (for example to check for conflicts, etc).    // FIXME: This needs to happen before we merge declarations. Then, @@ -4661,7 +4745,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,    if (Redeclaration && Previous.isSingleResult()) {      const FunctionDecl *Def;      FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl()); -    if (PrevFD && PrevFD->hasBody(Def) && D.hasAttributes()) { +    if (PrevFD && PrevFD->isDefined(Def) && D.hasAttributes()) {        Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition);        Diag(Def->getLocation(), diag::note_previous_definition);      } @@ -5076,9 +5160,11 @@ namespace {        if (OrigDecl != ReferenceDecl) return;        LookupResult Result(S, DRE->getNameInfo(), Sema::LookupOrdinaryName,                            Sema::NotForRedeclaration); -      S.Diag(SubExpr->getLocStart(), diag::warn_uninit_self_reference_in_init) -        << Result.getLookupName() << OrigDecl->getLocation() -        << SubExpr->getSourceRange(); +      S.DiagRuntimeBehavior(SubExpr->getLocStart(), SubExpr, +                            S.PDiag(diag::warn_uninit_self_reference_in_init) +                              << Result.getLookupName()  +                              << OrigDecl->getLocation() +                              << SubExpr->getSourceRange());      }    };  } @@ -5553,40 +5639,53 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,        return;      } -    const RecordType *Record -      = Context.getBaseElementType(Type)->getAs<RecordType>(); -    if (Record && getLangOptions().CPlusPlus && -        cast<CXXRecordDecl>(Record->getDecl())->isPOD()) { -      // C++03 [dcl.init]p9: -      //   If no initializer is specified for an object, and the -      //   object is of (possibly cv-qualified) non-POD class type (or -      //   array thereof), the object shall be default-initialized; if -      //   the object is of const-qualified type, the underlying class -      //   type shall have a user-declared default -      //   constructor. Otherwise, if no initializer is specified for -      //   a non- static object, the object and its subobjects, if -      //   any, have an indeterminate initial value); if the object -      //   or any of its subobjects are of const-qualified type, the -      //   program is ill-formed. -    } else { -      // Check for jumps past the implicit initializer.  C++0x -      // clarifies that this applies to a "variable with automatic -      // storage duration", not a "local variable". -      if (getLangOptions().CPlusPlus && Var->hasLocalStorage()) -        getCurFunction()->setHasBranchProtectedScope(); - -      InitializedEntity Entity = InitializedEntity::InitializeVariable(Var); -      InitializationKind Kind -        = InitializationKind::CreateDefault(Var->getLocation()); -     -      InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); -      ExprResult Init = InitSeq.Perform(*this, Entity, Kind, -                                        MultiExprArg(*this, 0, 0)); -      if (Init.isInvalid()) -        Var->setInvalidDecl(); -      else if (Init.get()) -        Var->setInit(MaybeCreateExprWithCleanups(Init.get())); +    // Check for jumps past the implicit initializer.  C++0x +    // clarifies that this applies to a "variable with automatic +    // storage duration", not a "local variable". +    // C++0x [stmt.dcl]p3 +    //   A program that jumps from a point where a variable with automatic +    //   storage duration is not in scope to a point where it is in scope is +    //   ill-formed unless the variable has scalar type, class type with a +    //   trivial default constructor and a trivial destructor, a cv-qualified +    //   version of one of these types, or an array of one of the preceding +    //   types and is declared without an initializer. +    if (getLangOptions().CPlusPlus && Var->hasLocalStorage()) { +      if (const RecordType *Record +            = Context.getBaseElementType(Type)->getAs<RecordType>()) { +        CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record->getDecl()); +        if ((!getLangOptions().CPlusPlus0x && !CXXRecord->isPOD()) || +            (getLangOptions().CPlusPlus0x && +             (!CXXRecord->hasTrivialDefaultConstructor() || +              !CXXRecord->hasTrivialDestructor()))) +          getCurFunction()->setHasBranchProtectedScope(); +      }      } +     +    // C++03 [dcl.init]p9: +    //   If no initializer is specified for an object, and the +    //   object is of (possibly cv-qualified) non-POD class type (or +    //   array thereof), the object shall be default-initialized; if +    //   the object is of const-qualified type, the underlying class +    //   type shall have a user-declared default +    //   constructor. Otherwise, if no initializer is specified for +    //   a non- static object, the object and its subobjects, if +    //   any, have an indeterminate initial value); if the object +    //   or any of its subobjects are of const-qualified type, the +    //   program is ill-formed. +    // C++0x [dcl.init]p11: +    //   If no initializer is specified for an object, the object is +    //   default-initialized; [...]. +    InitializedEntity Entity = InitializedEntity::InitializeVariable(Var); +    InitializationKind Kind +      = InitializationKind::CreateDefault(Var->getLocation()); +     +    InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); +    ExprResult Init = InitSeq.Perform(*this, Entity, Kind, +                                      MultiExprArg(*this, 0, 0)); +    if (Init.isInvalid()) +      Var->setInvalidDecl(); +    else if (Init.get()) +      Var->setInit(MaybeCreateExprWithCleanups(Init.get()));      CheckCompleteVariableDeclaration(Var);    } @@ -6056,7 +6155,7 @@ void Sema::CheckForFunctionRedefinition(FunctionDecl *FD) {    // Don't complain if we're in GNU89 mode and the previous definition    // was an extern inline function.    const FunctionDecl *Definition; -  if (FD->hasBody(Definition) && +  if (FD->isDefined(Definition) &&        !canRedefineFunction(Definition, getLangOptions())) {      if (getLangOptions().GNUMode && Definition->isInlineSpecified() &&          Definition->getStorageClass() == SC_Extern) @@ -6221,6 +6320,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,        WP.disableCheckFallThrough();      } +    // MSVC permits the use of pure specifier (=0) on function definition, +    // defined at class scope, warn about this non standard construct. +    if (getLangOptions().Microsoft && FD->isPure()) +      Diag(FD->getLocation(), diag::warn_pure_function_definition); +      if (!FD->isInvalidDecl()) {        DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());        DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(), @@ -6499,7 +6603,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,  ///  /// \returns true if the new tag kind is acceptable, false otherwise.  bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, -                                        TagTypeKind NewTag, +                                        TagTypeKind NewTag, bool isDefinition,                                          SourceLocation NewTagLoc,                                          const IdentifierInfo &Name) {    // C++ [dcl.type.elab]p3: @@ -6516,8 +6620,9 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,    //   struct class-key shall be used to refer to a class (clause 9)    //   declared using the class or struct class-key.    TagTypeKind OldTag = Previous->getTagKind(); -  if (OldTag == NewTag) -    return true; +  if (!isDefinition || (NewTag != TTK_Class && NewTag != TTK_Struct)) +    if (OldTag == NewTag) +      return true;    if ((OldTag == TTK_Struct || OldTag == TTK_Class) &&        (NewTag == TTK_Struct || NewTag == TTK_Class)) { @@ -6526,12 +6631,63 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,      if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous))        isTemplate = Record->getDescribedClassTemplate(); +    if (!ActiveTemplateInstantiations.empty()) { +      // In a template instantiation, do not offer fix-its for tag mismatches +      // since they usually mess up the template instead of fixing the problem. +      Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch) +        << (NewTag == TTK_Class) << isTemplate << &Name; +      return true; +    } + +    if (isDefinition) { +      // On definitions, check previous tags and issue a fix-it for each +      // one that doesn't match the current tag. +      if (Previous->getDefinition()) { +        // Don't suggest fix-its for redefinitions. +        return true; +      } + +      bool previousMismatch = false; +      for (TagDecl::redecl_iterator I(Previous->redecls_begin()), +           E(Previous->redecls_end()); I != E; ++I) { +        if (I->getTagKind() != NewTag) { +          if (!previousMismatch) { +            previousMismatch = true; +            Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch) +              << (NewTag == TTK_Class) << isTemplate << &Name; +          } +          Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion) +            << (NewTag == TTK_Class) +            << FixItHint::CreateReplacement(I->getInnerLocStart(), +                                            NewTag == TTK_Class? +                                            "class" : "struct"); +        } +      } +      return true; +    } + +    // Check for a previous definition.  If current tag and definition +    // are same type, do nothing.  If no definition, but disagree with +    // with previous tag type, give a warning, but no fix-it. +    const TagDecl *Redecl = Previous->getDefinition() ? +                            Previous->getDefinition() : Previous; +    if (Redecl->getTagKind() == NewTag) { +      return true; +    } +      Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)        << (NewTag == TTK_Class) -      << isTemplate << &Name -      << FixItHint::CreateReplacement(SourceRange(NewTagLoc), -                              OldTag == TTK_Class? "class" : "struct"); -    Diag(Previous->getLocation(), diag::note_previous_use); +      << isTemplate << &Name; +    Diag(Redecl->getLocation(), diag::note_previous_use); + +    // If there is a previous defintion, suggest a fix-it. +    if (Previous->getDefinition()) { +        Diag(NewTagLoc, diag::note_struct_class_suggestion) +          << (Redecl->getTagKind() == TTK_Class) +          << FixItHint::CreateReplacement(SourceRange(NewTagLoc), +                        Redecl->getTagKind() == TTK_Class? "class" : "struct"); +    } +      return true;    }    return false; @@ -6567,7 +6723,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,    if (TemplateParameterLists.size() > 0 ||        (SS.isNotEmpty() && TUK != TUK_Reference)) {      if (TemplateParameterList *TemplateParams -          = MatchTemplateParametersToScopeSpecifier(KWLoc, SS, +          = MatchTemplateParametersToScopeSpecifier(KWLoc, NameLoc, SS,                                                  TemplateParameterLists.get(),                                                  TemplateParameterLists.size(),                                                      TUK == TUK_Friend, @@ -6705,6 +6861,17 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,      // shouldn't be diagnosing.      LookupName(Previous, S); +    if (Previous.isAmbiguous() &&  +        (TUK == TUK_Definition || TUK == TUK_Declaration)) { +      LookupResult::Filter F = Previous.makeFilter(); +      while (F.hasNext()) { +        NamedDecl *ND = F.next(); +        if (ND->getDeclContext()->getRedeclContext() != SearchDC) +          F.erase(); +      } +      F.done(); +    } +          // Note:  there used to be some attempt at recovery here.      if (Previous.isAmbiguous())        return 0; @@ -6846,7 +7013,9 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,            isDeclInScope(PrevDecl, SearchDC, S, isExplicitSpecialization)) {          // Make sure that this wasn't declared as an enum and now used as a          // struct or something similar. -        if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind, KWLoc, *Name)) { +        if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind, +                                          TUK == TUK_Definition, KWLoc, +                                          *Name)) {            bool SafeToContinue              = (PrevTagDecl->getTagKind() != TTK_Enum &&                 Kind != TTK_Enum); @@ -6911,8 +7080,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,            // for the consumer of this Decl to know it doesn't own it.            // For our current ASTs this shouldn't be a problem, but will            // need to be changed with DeclGroups. -          if ((TUK == TUK_Reference && !PrevTagDecl->getFriendObjectKind()) || -              TUK == TUK_Friend) +          if ((TUK == TUK_Reference && (!PrevTagDecl->getFriendObjectKind() || +               getLangOptions().Microsoft)) || TUK == TUK_Friend)              return PrevTagDecl;            // Diagnose attempts to redefine a tag. @@ -7154,8 +7323,12 @@ CreateNewDecl:    New->setLexicalDeclContext(CurContext);    // Mark this as a friend decl if applicable. +  // In Microsoft mode, a friend declaration also acts as a forward +  // declaration so we always pass true to setObjectOfFriendDecl to make +  // the tag name visible.    if (TUK == TUK_Friend) -    New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty()); +    New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty() || +                               getLangOptions().Microsoft);    // Set the access specifier.    if (!Invalid && SearchDC->isRecord()) @@ -7341,14 +7514,13 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,    return false;  } -/// ActOnField - Each field of a struct/union/class is passed into this in order +/// ActOnField - Each field of a C struct/union is passed into this in order  /// to create a FieldDecl object for it. -Decl *Sema::ActOnField(Scope *S, Decl *TagD, -                                 SourceLocation DeclStart, -                                 Declarator &D, ExprTy *BitfieldWidth) { +Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, +                       Declarator &D, ExprTy *BitfieldWidth) {    FieldDecl *Res = HandleField(S, cast_or_null<RecordDecl>(TagD),                                 DeclStart, D, static_cast<Expr*>(BitfieldWidth), -                               AS_public); +                               /*HasInit=*/false, AS_public);    return Res;  } @@ -7356,7 +7528,7 @@ Decl *Sema::ActOnField(Scope *S, Decl *TagD,  ///  FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,                               SourceLocation DeclStart, -                             Declarator &D, Expr *BitWidth, +                             Declarator &D, Expr *BitWidth, bool HasInit,                               AccessSpecifier AS) {    IdentifierInfo *II = D.getIdentifier();    SourceLocation Loc = DeclStart; @@ -7405,8 +7577,8 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,      = (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable);    SourceLocation TSSL = D.getSourceRange().getBegin();    FieldDecl *NewFD -    = CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, TSSL, -                     AS, PrevDecl, &D); +    = CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, HasInit, +                     TSSL, AS, PrevDecl, &D);    if (NewFD->isInvalidDecl())      Record->setInvalidDecl(); @@ -7435,7 +7607,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,  FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,                                  TypeSourceInfo *TInfo,                                  RecordDecl *Record, SourceLocation Loc, -                                bool Mutable, Expr *BitWidth, +                                bool Mutable, Expr *BitWidth, bool HasInit,                                  SourceLocation TSSL,                                  AccessSpecifier AS, NamedDecl *PrevDecl,                                  Declarator *D) { @@ -7515,7 +7687,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,    }    FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo, -                                       BitWidth, Mutable); +                                       BitWidth, Mutable, HasInit);    if (InvalidDecl)      NewFD->setInvalidDecl(); @@ -7535,8 +7707,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,            // destructor, or a non-trivial copy assignment operator            // cannot be a member of a union, nor can an array of such            // objects. -          // TODO: C++0x alters this restriction significantly. -          if (CheckNontrivialField(NewFD)) +          if (!getLangOptions().CPlusPlus0x && CheckNontrivialField(NewFD))              NewFD->setInvalidDecl();          }        } @@ -7582,8 +7753,8 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {        CXXSpecialMember member = CXXInvalid;        if (!RDecl->hasTrivialCopyConstructor())          member = CXXCopyConstructor; -      else if (!RDecl->hasTrivialConstructor()) -        member = CXXConstructor; +      else if (!RDecl->hasTrivialDefaultConstructor()) +        member = CXXDefaultConstructor;        else if (!RDecl->hasTrivialCopyAssignment())          member = CXXCopyAssignment;        else if (!RDecl->hasTrivialDestructor()) @@ -7612,7 +7783,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {    case CXXInvalid:      break; -  case CXXConstructor: +  case CXXDefaultConstructor:      if (RD->hasUserDeclaredConstructor()) {        typedef CXXRecordDecl::ctor_iterator ctor_iter;        for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce;++ci){ @@ -7633,7 +7804,15 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {    case CXXCopyConstructor:      if (RD->hasUserDeclaredCopyConstructor()) {        SourceLocation CtorLoc = -        RD->getCopyConstructor(Context, 0)->getLocation(); +        RD->getCopyConstructor(0)->getLocation(); +      Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member; +      return; +    } +    break; + +  case CXXMoveConstructor: +    if (RD->hasUserDeclaredMoveConstructor()) { +      SourceLocation CtorLoc = RD->getMoveConstructor()->getLocation();        Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;        return;      } @@ -7649,6 +7828,14 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {      }      break; +  case CXXMoveAssignment: +    if (RD->hasUserDeclaredMoveAssignment()) { +      SourceLocation AssignLoc = RD->getMoveAssignmentOperator()->getLocation(); +      Diag(AssignLoc, diag::note_nontrivial_user_defined) << QT << member; +      return; +    } +    break; +    case CXXDestructor:      if (RD->hasUserDeclaredDestructor()) {        SourceLocation DtorLoc = LookupDestructor(RD)->getLocation(); @@ -7686,8 +7873,8 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {    bool (CXXRecordDecl::*hasTrivial)() const;    switch (member) { -  case CXXConstructor: -    hasTrivial = &CXXRecordDecl::hasTrivialConstructor; break; +  case CXXDefaultConstructor: +    hasTrivial = &CXXRecordDecl::hasTrivialDefaultConstructor; break;    case CXXCopyConstructor:      hasTrivial = &CXXRecordDecl::hasTrivialCopyConstructor; break;    case CXXCopyAssignment: @@ -8047,6 +8234,11 @@ void Sema::ActOnFields(Scope* S,            Convs->setAccess(I, (*I)->getAccess());          if (!CXXRecord->isDependentType()) { +          // Adjust user-defined destructor exception spec. +          if (getLangOptions().CPlusPlus0x && +              CXXRecord->hasUserDeclaredDestructor()) +            AdjustDestructorExceptionSpec(CXXRecord,CXXRecord->getDestructor()); +            // Add any implicitly-declared members to this class.            AddImplicitlyDeclaredMembersToClass(CXXRecord); @@ -8095,6 +8287,22 @@ void Sema::ActOnFields(Scope* S,      if (!Completed)        Record->completeDefinition(); + +    // Now that the record is complete, do any delayed exception spec checks +    // we were missing. +    while (!DelayedDestructorExceptionSpecChecks.empty()) { +      const CXXDestructorDecl *Dtor = +              DelayedDestructorExceptionSpecChecks.back().first; +      if (Dtor->getParent() != Record) +        break; + +      assert(!Dtor->getParent()->isDependentType() && +          "Should not ever add destructors of templates into the list."); +      CheckOverridingFunctionExceptionSpec(Dtor, +          DelayedDestructorExceptionSpecChecks.back().second); +      DelayedDestructorExceptionSpecChecks.pop_back(); +    } +    } else {      ObjCIvarDecl **ClsFields =        reinterpret_cast<ObjCIvarDecl**>(RecFields.data()); @@ -8149,7 +8357,7 @@ static bool isRepresentableIntegerValue(ASTContext &Context,    unsigned BitWidth = Context.getIntWidth(T);    if (Value.isUnsigned() || Value.isNonNegative()) { -    if (T->isSignedIntegerType())  +    if (T->isSignedIntegerOrEnumerationType())         --BitWidth;      return Value.getActiveBits() <= BitWidth;    }   @@ -8172,8 +8380,8 @@ static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) {    };    unsigned BitWidth = Context.getTypeSize(T); -  QualType *Types = T->isSignedIntegerType()? SignedIntegralTypes -                                            : UnsignedIntegralTypes; +  QualType *Types = T->isSignedIntegerOrEnumerationType()? SignedIntegralTypes +                                                        : UnsignedIntegralTypes;    for (unsigned I = 0; I != NumTypes; ++I)      if (Context.getTypeSize(Types[I]) > BitWidth)        return Types[I]; @@ -8307,7 +8515,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,          // type that is supposed to be large enough to represent the incremented          // value, then increment.          EnumVal = LastEnumConst->getInitVal(); -        EnumVal.setIsSigned(EltTy->isSignedIntegerType()); +        EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType());          EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy));          ++EnumVal;         @@ -8331,7 +8539,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,      // Make the enumerator value match the signedness and size of the       // enumerator's type.      EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy)); -    EnumVal.setIsSigned(EltTy->isSignedIntegerType()); +    EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType());    }    return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy, @@ -8589,7 +8797,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,      } else {        NewTy = BestType;        NewWidth = BestWidth; -      NewSign = BestType->isSignedIntegerType(); +      NewSign = BestType->isSignedIntegerOrEnumerationType();      }      // Adjust the APSInt value. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index 27632a1a57c4..ce99efbd0bd2 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -111,6 +111,102 @@ namespace {    }  } +void Sema::ImplicitExceptionSpecification::CalledDecl(CXXMethodDecl *Method) { +  assert(Context && "ImplicitExceptionSpecification without an ASTContext"); +  // If we have an MSAny or unknown spec already, don't bother. +  if (!Method || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed) +    return; + +  const FunctionProtoType *Proto +    = Method->getType()->getAs<FunctionProtoType>(); + +  ExceptionSpecificationType EST = Proto->getExceptionSpecType(); + +  // If this function can throw any exceptions, make a note of that. +  if (EST == EST_Delayed || EST == EST_MSAny || EST == EST_None) { +    ClearExceptions(); +    ComputedEST = EST; +    return; +  } + +  // FIXME: If the call to this decl is using any of its default arguments, we +  // need to search them for potentially-throwing calls. + +  // If this function has a basic noexcept, it doesn't affect the outcome. +  if (EST == EST_BasicNoexcept) +    return; + +  // If we have a throw-all spec at this point, ignore the function. +  if (ComputedEST == EST_None) +    return; + +  // If we're still at noexcept(true) and there's a nothrow() callee, +  // change to that specification. +  if (EST == EST_DynamicNone) { +    if (ComputedEST == EST_BasicNoexcept) +      ComputedEST = EST_DynamicNone; +    return; +  } + +  // Check out noexcept specs. +  if (EST == EST_ComputedNoexcept) { +    FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(*Context); +    assert(NR != FunctionProtoType::NR_NoNoexcept && +           "Must have noexcept result for EST_ComputedNoexcept."); +    assert(NR != FunctionProtoType::NR_Dependent && +           "Should not generate implicit declarations for dependent cases, " +           "and don't know how to handle them anyway."); + +    // noexcept(false) -> no spec on the new function +    if (NR == FunctionProtoType::NR_Throw) { +      ClearExceptions(); +      ComputedEST = EST_None; +    } +    // noexcept(true) won't change anything either. +    return; +  } + +  assert(EST == EST_Dynamic && "EST case not considered earlier."); +  assert(ComputedEST != EST_None && +         "Shouldn't collect exceptions when throw-all is guaranteed."); +  ComputedEST = EST_Dynamic; +  // Record the exceptions in this function's exception specification. +  for (FunctionProtoType::exception_iterator E = Proto->exception_begin(), +                                          EEnd = Proto->exception_end(); +       E != EEnd; ++E) +    if (ExceptionsSeen.insert(Context->getCanonicalType(*E))) +      Exceptions.push_back(*E); +} + +void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) { +  if (!E || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed) +    return; + +  // FIXME: +  // +  // C++0x [except.spec]p14: +  //   [An] implicit exception-specification specifies the type-id T if and +  // only if T is allowed by the exception-specification of a function directly +  // invoked by f’s implicit definition; f shall allow all exceptions if any +  // function it directly invokes allows all exceptions, and f shall allow no +  // exceptions if every function it directly invokes allows no exceptions. +  // +  // Note in particular that if an implicit exception-specification is generated +  // for a function containing a throw-expression, that specification can still +  // be noexcept(true). +  // +  // Note also that 'directly invoked' is not defined in the standard, and there +  // is no indication that we should only consider potentially-evaluated calls. +  // +  // Ultimately we should implement the intent of the standard: the exception +  // specification should be the set of exceptions which can be thrown by the +  // implicit definition. For now, we assume that any non-nothrow expression can +  // throw any exception. + +  if (E->CanThrow(*Context)) +    ComputedEST = EST_None; +} +  bool  Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,                                SourceLocation EqualLoc) { @@ -393,6 +489,15 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {               diag::err_param_default_argument_member_template_redecl)            << WhichKind            << NewParam->getDefaultArgRange(); +      } else if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(New)) { +        CXXSpecialMember NewSM = getSpecialMember(Ctor), +                         OldSM = getSpecialMember(cast<CXXConstructorDecl>(Old)); +        if (NewSM != OldSM) { +          Diag(NewParam->getLocation(),diag::warn_default_arg_makes_ctor_special) +            << NewParam->getDefaultArgRange() << NewSM; +          Diag(Old->getLocation(), diag::note_previous_declaration_special) +            << OldSM; +        }        }      }    } @@ -956,14 +1061,15 @@ bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,  /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member  /// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the -/// bitfield width if there is one and 'InitExpr' specifies the initializer if -/// any. +/// bitfield width if there is one, 'InitExpr' specifies the initializer if +/// one has been parsed, and 'HasDeferredInit' is true if an initializer is +/// present but parsing it has been deferred.  Decl *  Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,                                 MultiTemplateParamsArg TemplateParameterLists,                                 ExprTy *BW, const VirtSpecifiers &VS, -                               ExprTy *InitExpr, bool IsDefinition, -                               bool Deleted) { +                               ExprTy *InitExpr, bool HasDeferredInit, +                               bool IsDefinition) {    const DeclSpec &DS = D.getDeclSpec();    DeclarationNameInfo NameInfo = GetNameForDeclarator(D);    DeclarationName Name = NameInfo.getName(); @@ -978,6 +1084,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,    assert(isa<CXXRecordDecl>(CurContext));    assert(!DS.isFriendSpecified()); +  assert(!Init || !HasDeferredInit);    bool isFunc = false;    if (D.isFunctionDeclarator()) @@ -1028,7 +1135,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,    if (isInstField) {      CXXScopeSpec &SS = D.getCXXScopeSpec(); -          if (SS.isSet() && !SS.isInvalid()) {        // The user provided a superfluous scope specifier inside a class        // definition: @@ -1050,9 +1156,11 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,      // FIXME: Check for template parameters!      // FIXME: Check that the name is an identifier!      Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth, -                         AS); +                         HasDeferredInit, AS);      assert(Member && "HandleField never returns null");    } else { +    assert(!HasDeferredInit); +      Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition);      if (!Member) {        return 0; @@ -1123,8 +1231,14 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,    if (Init)      AddInitializerToDecl(Member, Init, false,                           DS.getTypeSpecType() == DeclSpec::TST_auto); -  if (Deleted) // FIXME: Source location is not very good. -    SetDeclDeleted(Member, D.getSourceRange().getBegin()); +  else if (DS.getTypeSpecType() == DeclSpec::TST_auto && +           DS.getStorageClassSpec() == DeclSpec::SCS_static) { +    // C++0x [dcl.spec.auto]p4: 'auto' can only be used in the type of a static +    // data member if a brace-or-equal-initializer is provided. +    Diag(Loc, diag::err_auto_var_requires_init) +      << Name << cast<ValueDecl>(Member)->getType(); +    Member->setInvalidDecl(); +  }    FinalizeDeclaration(Member); @@ -1133,6 +1247,47 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,    return Member;  } +/// ActOnCXXInClassMemberInitializer - This is invoked after parsing an +/// in-class initializer for a non-static C++ class member. Such parsing +/// is deferred until the class is complete. +void +Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation EqualLoc, +                                       Expr *InitExpr) { +  FieldDecl *FD = cast<FieldDecl>(D); + +  if (!InitExpr) { +    FD->setInvalidDecl(); +    FD->removeInClassInitializer(); +    return; +  } + +  ExprResult Init = InitExpr; +  if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { +    // FIXME: if there is no EqualLoc, this is list-initialization. +    Init = PerformCopyInitialization( +      InitializedEntity::InitializeMember(FD), EqualLoc, InitExpr); +    if (Init.isInvalid()) { +      FD->setInvalidDecl(); +      return; +    } + +    CheckImplicitConversions(Init.get(), EqualLoc); +  } + +  // C++0x [class.base.init]p7: +  //   The initialization of each base and member constitutes a +  //   full-expression. +  Init = MaybeCreateExprWithCleanups(Init); +  if (Init.isInvalid()) { +    FD->setInvalidDecl(); +    return; +  } + +  InitExpr = Init.release(); + +  FD->setInClassInitializer(InitExpr); +} +  /// \brief Find the direct and/or virtual base specifiers that  /// correspond to the given base type, for use in base initialization  /// within a constructor. @@ -1547,7 +1702,8 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo,      return true;    CXXConstructExpr *ConExpr = cast<CXXConstructExpr>(DelegationInit.get()); -  CXXConstructorDecl *Constructor = ConExpr->getConstructor(); +  CXXConstructorDecl *Constructor +    = ConExpr->getConstructor();    assert(Constructor && "Delegating constructor with no target?");    CheckImplicitConversions(DelegationInit.get(), LParenLoc); @@ -1956,24 +2112,26 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,      return false;    } -  if (FieldBaseElementType->isReferenceType()) { -    SemaRef.Diag(Constructor->getLocation(),  -                 diag::err_uninitialized_member_in_ctor) -    << (int)Constructor->isImplicit()  -    << SemaRef.Context.getTagDeclType(Constructor->getParent()) -    << 0 << Field->getDeclName(); -    SemaRef.Diag(Field->getLocation(), diag::note_declared_at); -    return true; -  } +  if (!Field->getParent()->isUnion()) { +    if (FieldBaseElementType->isReferenceType()) { +      SemaRef.Diag(Constructor->getLocation(),  +                   diag::err_uninitialized_member_in_ctor) +      << (int)Constructor->isImplicit()  +      << SemaRef.Context.getTagDeclType(Constructor->getParent()) +      << 0 << Field->getDeclName(); +      SemaRef.Diag(Field->getLocation(), diag::note_declared_at); +      return true; +    } -  if (FieldBaseElementType.isConstQualified()) { -    SemaRef.Diag(Constructor->getLocation(),  -                 diag::err_uninitialized_member_in_ctor) -    << (int)Constructor->isImplicit()  -    << SemaRef.Context.getTagDeclType(Constructor->getParent()) -    << 1 << Field->getDeclName(); -    SemaRef.Diag(Field->getLocation(), diag::note_declared_at); -    return true; +    if (FieldBaseElementType.isConstQualified()) { +      SemaRef.Diag(Constructor->getLocation(),  +                   diag::err_uninitialized_member_in_ctor) +      << (int)Constructor->isImplicit()  +      << SemaRef.Context.getTagDeclType(Constructor->getParent()) +      << 1 << Field->getDeclName(); +      SemaRef.Diag(Field->getLocation(), diag::note_declared_at); +      return true; +    }    }    // Nothing to initialize. @@ -2001,7 +2159,7 @@ struct BaseAndFieldInfo {  };  } -static bool CollectFieldInitializer(BaseAndFieldInfo &Info, +static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,                                      FieldDecl *Top, FieldDecl *Field) {    // Overwhelmingly common case: we have a direct initializer for this field. @@ -2010,6 +2168,18 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info,      return false;    } +  // C++0x [class.base.init]p8: if the entity is a non-static data member that +  // has a brace-or-equal-initializer, the entity is initialized as specified +  // in [dcl.init]. +  if (Field->hasInClassInitializer()) { +    Info.AllToInit.push_back( +      new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field, +                                               SourceLocation(), +                                               SourceLocation(), 0, +                                               SourceLocation())); +    return false; +  } +    if (Info.IIK == IIK_Default && Field->isAnonymousStructOrUnion()) {      const RecordType *FieldClassType = Field->getType()->getAs<RecordType>();      assert(FieldClassType && "anonymous struct/union without record type"); @@ -2032,7 +2202,7 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info,            // field in the class is also initialized, so exit immediately.            return false;          } else if ((*FA)->isAnonymousStructOrUnion()) { -          if (CollectFieldInitializer(Info, Top, *FA)) +          if (CollectFieldInitializer(SemaRef, Info, Top, *FA))              return true;          }        } @@ -2047,7 +2217,7 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info,        // necessary.        for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),             EA = FieldClassDecl->field_end(); FA != EA; FA++) { -        if (CollectFieldInitializer(Info, Top, *FA)) +        if (CollectFieldInitializer(SemaRef, Info, Top, *FA))            return true;        }      } @@ -2056,7 +2226,7 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info,    // Don't try to build an implicit initializer if there were semantic    // errors in any of the initializers (and therefore we might be    // missing some that the user actually wrote). -  if (Info.AnyErrorsInInits) +  if (Info.AnyErrorsInInits || Field->isInvalidDecl())      return false;    CXXCtorInitializer *Init = 0; @@ -2072,26 +2242,22 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info,  bool  Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor,                                 CXXCtorInitializer *Initializer) { +  assert(Initializer->isDelegatingInitializer());    Constructor->setNumCtorInitializers(1);    CXXCtorInitializer **initializer =      new (Context) CXXCtorInitializer*[1];    memcpy(initializer, &Initializer, sizeof (CXXCtorInitializer*));    Constructor->setCtorInitializers(initializer); -  // FIXME: This doesn't catch indirect loops yet -  CXXConstructorDecl *Target = Initializer->getTargetConstructor(); -  while (Target) { -    if (Target == Constructor) { -      Diag(Initializer->getSourceLocation(), diag::err_delegating_ctor_loop) -        << Constructor; -      return true; -    } -    Target = Target->getTargetConstructor(); +  if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) { +    MarkDeclarationReferenced(Initializer->getSourceLocation(), Dtor); +    DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation());    } +  DelegatingCtorDecls.push_back(Constructor); +    return false;  } -  bool  Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, @@ -2192,7 +2358,7 @@ Sema::SetCtorInitializers(CXXConstructorDecl *Constructor,               "Incomplete array type is not valid");        continue;      } -    if (CollectFieldInitializer(Info, *Field, *Field)) +    if (CollectFieldInitializer(*this, Info, *Field, *Field))        HadError = true;    } @@ -2468,7 +2634,7 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,          HadError = true;          // We will treat this as being the only initializer.        } -      SetDelegatingInitializer(Constructor, *MemInits); +      SetDelegatingInitializer(Constructor, MemInits[i]);        // Return immediately as the initializer is set.        return;      } @@ -2805,7 +2971,7 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info,                                      CXXMethodDecl *MD) {    // No need to do the check on definitions, which require that    // the return/param types be complete. -  if (MD->isThisDeclarationADefinition()) +  if (MD->doesThisDeclarationHaveABody())      return;    // For safety's sake, just ignore it if we don't have type source @@ -2871,6 +3037,9 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {      for (RecordDecl::field_iterator F = Record->field_begin(),                                    FEnd = Record->field_end();           F != FEnd; ++F) { +      if (F->hasInClassInitializer()) +        continue; +        if (F->getType()->isReferenceType() ||            (F->getType().isConstQualified() && F->getType()->isScalarType())) {          if (!Complained) { @@ -2937,6 +3106,953 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {    //   instantiated (e.g. meta-functions). This doesn't apply to classes that    //   have inherited constructors.    DeclareInheritedConstructors(Record); + +  if (!Record->isDependentType()) +    CheckExplicitlyDefaultedMethods(Record); +} + +void Sema::CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record) { +  for (CXXRecordDecl::method_iterator MI = Record->method_begin(), +                                      ME = Record->method_end(); +       MI != ME; ++MI) { +    if (!MI->isInvalidDecl() && MI->isExplicitlyDefaulted()) { +      switch (getSpecialMember(*MI)) { +      case CXXDefaultConstructor: +        CheckExplicitlyDefaultedDefaultConstructor( +                                                  cast<CXXConstructorDecl>(*MI)); +        break; + +      case CXXDestructor: +        CheckExplicitlyDefaultedDestructor(cast<CXXDestructorDecl>(*MI)); +        break; + +      case CXXCopyConstructor: +        CheckExplicitlyDefaultedCopyConstructor(cast<CXXConstructorDecl>(*MI)); +        break; + +      case CXXCopyAssignment: +        CheckExplicitlyDefaultedCopyAssignment(*MI); +        break; + +      case CXXMoveConstructor: +      case CXXMoveAssignment: +        Diag(MI->getLocation(), diag::err_defaulted_move_unsupported); +        break; + +      default: +        // FIXME: Do moves once they exist +        llvm_unreachable("non-special member explicitly defaulted!"); +      } +    } +  } + +} + +void Sema::CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *CD) { +  assert(CD->isExplicitlyDefaulted() && CD->isDefaultConstructor()); +   +  // Whether this was the first-declared instance of the constructor. +  // This affects whether we implicitly add an exception spec (and, eventually, +  // constexpr). It is also ill-formed to explicitly default a constructor such +  // that it would be deleted. (C++0x [decl.fct.def.default]) +  bool First = CD == CD->getCanonicalDecl(); + +  bool HadError = false; +  if (CD->getNumParams() != 0) { +    Diag(CD->getLocation(), diag::err_defaulted_default_ctor_params) +      << CD->getSourceRange(); +    HadError = true; +  } + +  ImplicitExceptionSpecification Spec +    = ComputeDefaultedDefaultCtorExceptionSpec(CD->getParent()); +  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); +  if (EPI.ExceptionSpecType == EST_Delayed) { +    // Exception specification depends on some deferred part of the class. We'll +    // try again when the class's definition has been fully processed. +    return; +  } +  const FunctionProtoType *CtorType = CD->getType()->getAs<FunctionProtoType>(), +                          *ExceptionType = Context.getFunctionType( +                         Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); + +  if (CtorType->hasExceptionSpec()) { +    if (CheckEquivalentExceptionSpec( +          PDiag(diag::err_incorrect_defaulted_exception_spec) +            << CXXDefaultConstructor, +          PDiag(), +          ExceptionType, SourceLocation(), +          CtorType, CD->getLocation())) { +      HadError = true; +    } +  } else if (First) { +    // We set the declaration to have the computed exception spec here. +    // We know there are no parameters. +    EPI.ExtInfo = CtorType->getExtInfo(); +    CD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); +  } + +  if (HadError) { +    CD->setInvalidDecl(); +    return; +  } + +  if (ShouldDeleteDefaultConstructor(CD)) { +    if (First) { +      CD->setDeletedAsWritten(); +    } else { +      Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) +        << CXXDefaultConstructor; +      CD->setInvalidDecl(); +    } +  } +} + +void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) { +  assert(CD->isExplicitlyDefaulted() && CD->isCopyConstructor()); + +  // Whether this was the first-declared instance of the constructor. +  bool First = CD == CD->getCanonicalDecl(); + +  bool HadError = false; +  if (CD->getNumParams() != 1) { +    Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_params) +      << CD->getSourceRange(); +    HadError = true; +  } + +  ImplicitExceptionSpecification Spec(Context); +  bool Const; +  llvm::tie(Spec, Const) = +    ComputeDefaultedCopyCtorExceptionSpecAndConst(CD->getParent()); +   +  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); +  const FunctionProtoType *CtorType = CD->getType()->getAs<FunctionProtoType>(), +                          *ExceptionType = Context.getFunctionType( +                         Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); + +  // Check for parameter type matching. +  // This is a copy ctor so we know it's a cv-qualified reference to T. +  QualType ArgType = CtorType->getArgType(0); +  if (ArgType->getPointeeType().isVolatileQualified()) { +    Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_volatile_param); +    HadError = true; +  } +  if (ArgType->getPointeeType().isConstQualified() && !Const) { +    Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_const_param); +    HadError = true; +  } + +  if (CtorType->hasExceptionSpec()) { +    if (CheckEquivalentExceptionSpec( +          PDiag(diag::err_incorrect_defaulted_exception_spec) +            << CXXCopyConstructor, +          PDiag(), +          ExceptionType, SourceLocation(), +          CtorType, CD->getLocation())) { +      HadError = true; +    } +  } else if (First) { +    // We set the declaration to have the computed exception spec here. +    // We duplicate the one parameter type. +    EPI.ExtInfo = CtorType->getExtInfo(); +    CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); +  } + +  if (HadError) { +    CD->setInvalidDecl(); +    return; +  } + +  if (ShouldDeleteCopyConstructor(CD)) { +    if (First) { +      CD->setDeletedAsWritten(); +    } else { +      Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) +        << CXXCopyConstructor; +      CD->setInvalidDecl(); +    } +  } +} + +void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) { +  assert(MD->isExplicitlyDefaulted()); + +  // Whether this was the first-declared instance of the operator +  bool First = MD == MD->getCanonicalDecl(); + +  bool HadError = false; +  if (MD->getNumParams() != 1) { +    Diag(MD->getLocation(), diag::err_defaulted_copy_assign_params) +      << MD->getSourceRange(); +    HadError = true; +  } + +  QualType ReturnType = +    MD->getType()->getAs<FunctionType>()->getResultType(); +  if (!ReturnType->isLValueReferenceType() || +      !Context.hasSameType( +        Context.getCanonicalType(ReturnType->getPointeeType()), +        Context.getCanonicalType(Context.getTypeDeclType(MD->getParent())))) { +    Diag(MD->getLocation(), diag::err_defaulted_copy_assign_return_type); +    HadError = true; +  } + +  ImplicitExceptionSpecification Spec(Context); +  bool Const; +  llvm::tie(Spec, Const) = +    ComputeDefaultedCopyCtorExceptionSpecAndConst(MD->getParent()); +   +  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); +  const FunctionProtoType *OperType = MD->getType()->getAs<FunctionProtoType>(), +                          *ExceptionType = Context.getFunctionType( +                         Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); + +  QualType ArgType = OperType->getArgType(0); +  if (!ArgType->isReferenceType()) { +    Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref); +    HadError = true; +  } else { +    if (ArgType->getPointeeType().isVolatileQualified()) { +      Diag(MD->getLocation(), diag::err_defaulted_copy_assign_volatile_param); +      HadError = true; +    } +    if (ArgType->getPointeeType().isConstQualified() && !Const) { +      Diag(MD->getLocation(), diag::err_defaulted_copy_assign_const_param); +      HadError = true; +    } +  } + +  if (OperType->getTypeQuals()) { +    Diag(MD->getLocation(), diag::err_defaulted_copy_assign_quals); +    HadError = true; +  } + +  if (OperType->hasExceptionSpec()) { +    if (CheckEquivalentExceptionSpec( +          PDiag(diag::err_incorrect_defaulted_exception_spec) +            << CXXCopyAssignment, +          PDiag(), +          ExceptionType, SourceLocation(), +          OperType, MD->getLocation())) { +      HadError = true; +    } +  } else if (First) { +    // We set the declaration to have the computed exception spec here. +    // We duplicate the one parameter type. +    EPI.RefQualifier = OperType->getRefQualifier(); +    EPI.ExtInfo = OperType->getExtInfo(); +    MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI)); +  } + +  if (HadError) { +    MD->setInvalidDecl(); +    return; +  } + +  if (ShouldDeleteCopyAssignmentOperator(MD)) { +    if (First) { +      MD->setDeletedAsWritten(); +    } else { +      Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) +        << CXXCopyAssignment; +      MD->setInvalidDecl(); +    } +  } +} + +void Sema::CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *DD) { +  assert(DD->isExplicitlyDefaulted()); + +  // Whether this was the first-declared instance of the destructor. +  bool First = DD == DD->getCanonicalDecl(); + +  ImplicitExceptionSpecification Spec +    = ComputeDefaultedDtorExceptionSpec(DD->getParent()); +  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); +  const FunctionProtoType *DtorType = DD->getType()->getAs<FunctionProtoType>(), +                          *ExceptionType = Context.getFunctionType( +                         Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); + +  if (DtorType->hasExceptionSpec()) { +    if (CheckEquivalentExceptionSpec( +          PDiag(diag::err_incorrect_defaulted_exception_spec) +            << CXXDestructor, +          PDiag(), +          ExceptionType, SourceLocation(), +          DtorType, DD->getLocation())) { +      DD->setInvalidDecl(); +      return; +    } +  } else if (First) { +    // We set the declaration to have the computed exception spec here. +    // There are no parameters. +    EPI.ExtInfo = DtorType->getExtInfo(); +    DD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); +  } + +  if (ShouldDeleteDestructor(DD)) { +    if (First) { +      DD->setDeletedAsWritten(); +    } else { +      Diag(DD->getLocation(), diag::err_out_of_line_default_deletes) +        << CXXDestructor; +      DD->setInvalidDecl(); +    } +  } +} + +bool Sema::ShouldDeleteDefaultConstructor(CXXConstructorDecl *CD) { +  CXXRecordDecl *RD = CD->getParent(); +  assert(!RD->isDependentType() && "do deletion after instantiation"); +  if (!LangOpts.CPlusPlus0x) +    return false; + +  SourceLocation Loc = CD->getLocation(); + +  // Do access control from the constructor +  ContextRAII CtorContext(*this, CD); + +  bool Union = RD->isUnion(); +  bool AllConst = true; + +  // We do this because we should never actually use an anonymous +  // union's constructor. +  if (Union && RD->isAnonymousStructOrUnion()) +    return false; + +  // FIXME: We should put some diagnostic logic right into this function. + +  // C++0x [class.ctor]/5 +  //    A defaulted default constructor for class X is defined as deleted if: + +  for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), +                                          BE = RD->bases_end(); +       BI != BE; ++BI) { +    // We'll handle this one later +    if (BI->isVirtual()) +      continue; + +    CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); +    assert(BaseDecl && "base isn't a CXXRecordDecl"); + +    // -- any [direct base class] has a type with a destructor that is +    //    deleted or inaccessible from the defaulted default constructor +    CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); +    if (BaseDtor->isDeleted()) +      return true; +    if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != +        AR_accessible) +      return true; + +    // -- any [direct base class either] has no default constructor or +    //    overload resolution as applied to [its] default constructor +    //    results in an ambiguity or in a function that is deleted or +    //    inaccessible from the defaulted default constructor +    CXXConstructorDecl *BaseDefault = LookupDefaultConstructor(BaseDecl); +    if (!BaseDefault || BaseDefault->isDeleted()) +      return true; + +    if (CheckConstructorAccess(Loc, BaseDefault, BaseDefault->getAccess(), +                               PDiag()) != AR_accessible) +      return true; +  } + +  for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), +                                          BE = RD->vbases_end(); +       BI != BE; ++BI) { +    CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); +    assert(BaseDecl && "base isn't a CXXRecordDecl"); + +    // -- any [virtual base class] has a type with a destructor that is +    //    delete or inaccessible from the defaulted default constructor +    CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); +    if (BaseDtor->isDeleted()) +      return true; +    if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != +        AR_accessible) +      return true; + +    // -- any [virtual base class either] has no default constructor or +    //    overload resolution as applied to [its] default constructor +    //    results in an ambiguity or in a function that is deleted or +    //    inaccessible from the defaulted default constructor +    CXXConstructorDecl *BaseDefault = LookupDefaultConstructor(BaseDecl); +    if (!BaseDefault || BaseDefault->isDeleted()) +      return true; + +    if (CheckConstructorAccess(Loc, BaseDefault, BaseDefault->getAccess(), +                               PDiag()) != AR_accessible) +      return true; +  } + +  for (CXXRecordDecl::field_iterator FI = RD->field_begin(), +                                     FE = RD->field_end(); +       FI != FE; ++FI) { +    if (FI->isInvalidDecl()) +      continue; +     +    QualType FieldType = Context.getBaseElementType(FI->getType()); +    CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); + +    // -- any non-static data member with no brace-or-equal-initializer is of +    //    reference type +    if (FieldType->isReferenceType() && !FI->hasInClassInitializer()) +      return true; + +    // -- X is a union and all its variant members are of const-qualified type +    //    (or array thereof) +    if (Union && !FieldType.isConstQualified()) +      AllConst = false; + +    if (FieldRecord) { +      // -- X is a union-like class that has a variant member with a non-trivial +      //    default constructor +      if (Union && !FieldRecord->hasTrivialDefaultConstructor()) +        return true; + +      CXXDestructorDecl *FieldDtor = LookupDestructor(FieldRecord); +      if (FieldDtor->isDeleted()) +        return true; +      if (CheckDestructorAccess(Loc, FieldDtor, PDiag()) != +          AR_accessible) +        return true; + +      // -- any non-variant non-static data member of const-qualified type (or +      //    array thereof) with no brace-or-equal-initializer does not have a +      //    user-provided default constructor +      if (FieldType.isConstQualified() && +          !FI->hasInClassInitializer() && +          !FieldRecord->hasUserProvidedDefaultConstructor()) +        return true; +  +      if (!Union && FieldRecord->isUnion() && +          FieldRecord->isAnonymousStructOrUnion()) { +        // We're okay to reuse AllConst here since we only care about the +        // value otherwise if we're in a union. +        AllConst = true; + +        for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), +                                           UE = FieldRecord->field_end(); +             UI != UE; ++UI) { +          QualType UnionFieldType = Context.getBaseElementType(UI->getType()); +          CXXRecordDecl *UnionFieldRecord = +            UnionFieldType->getAsCXXRecordDecl(); + +          if (!UnionFieldType.isConstQualified()) +            AllConst = false; + +          if (UnionFieldRecord && +              !UnionFieldRecord->hasTrivialDefaultConstructor()) +            return true; +        } + +        if (AllConst) +          return true; + +        // Don't try to initialize the anonymous union +        // This is technically non-conformant, but sanity demands it. +        continue; +      } + +      // -- any non-static data member with no brace-or-equal-initializer has +      //    class type M (or array thereof) and either M has no default +      //    constructor or overload resolution as applied to M's default +      //    constructor results in an ambiguity or in a function that is deleted +      //    or inaccessible from the defaulted default constructor. +      if (!FI->hasInClassInitializer()) { +        CXXConstructorDecl *FieldDefault = LookupDefaultConstructor(FieldRecord); +        if (!FieldDefault || FieldDefault->isDeleted()) +          return true; +        if (CheckConstructorAccess(Loc, FieldDefault, FieldDefault->getAccess(), +                                   PDiag()) != AR_accessible) +          return true; +      } +    } else if (!Union && FieldType.isConstQualified() && +               !FI->hasInClassInitializer()) { +      // -- any non-variant non-static data member of const-qualified type (or +      //    array thereof) with no brace-or-equal-initializer does not have a +      //    user-provided default constructor +      return true; +    } +  } + +  if (Union && AllConst) +    return true; + +  return false; +} + +bool Sema::ShouldDeleteCopyConstructor(CXXConstructorDecl *CD) { +  CXXRecordDecl *RD = CD->getParent(); +  assert(!RD->isDependentType() && "do deletion after instantiation"); +  if (!LangOpts.CPlusPlus0x) +    return false; + +  SourceLocation Loc = CD->getLocation(); + +  // Do access control from the constructor +  ContextRAII CtorContext(*this, CD); + +  bool Union = RD->isUnion(); + +  assert(!CD->getParamDecl(0)->getType()->getPointeeType().isNull() && +         "copy assignment arg has no pointee type"); +  unsigned ArgQuals = +    CD->getParamDecl(0)->getType()->getPointeeType().isConstQualified() ? +      Qualifiers::Const : 0; + +  // We do this because we should never actually use an anonymous +  // union's constructor. +  if (Union && RD->isAnonymousStructOrUnion()) +    return false; + +  // FIXME: We should put some diagnostic logic right into this function. + +  // C++0x [class.copy]/11 +  //    A defaulted [copy] constructor for class X is defined as delete if X has: + +  for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), +                                          BE = RD->bases_end(); +       BI != BE; ++BI) { +    // We'll handle this one later +    if (BI->isVirtual()) +      continue; + +    QualType BaseType = BI->getType(); +    CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl(); +    assert(BaseDecl && "base isn't a CXXRecordDecl"); + +    // -- any [direct base class] of a type with a destructor that is deleted or +    //    inaccessible from the defaulted constructor +    CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); +    if (BaseDtor->isDeleted()) +      return true; +    if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != +        AR_accessible) +      return true; + +    // -- a [direct base class] B that cannot be [copied] because overload +    //    resolution, as applied to B's [copy] constructor, results in an +    //    ambiguity or a function that is deleted or inaccessible from the +    //    defaulted constructor +    CXXConstructorDecl *BaseCtor = LookupCopyConstructor(BaseDecl, ArgQuals); +    if (!BaseCtor || BaseCtor->isDeleted()) +      return true; +    if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(), PDiag()) != +        AR_accessible) +      return true; +  } + +  for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), +                                          BE = RD->vbases_end(); +       BI != BE; ++BI) { +    QualType BaseType = BI->getType(); +    CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl(); +    assert(BaseDecl && "base isn't a CXXRecordDecl"); + +    // -- any [virtual base class] of a type with a destructor that is deleted or +    //    inaccessible from the defaulted constructor +    CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); +    if (BaseDtor->isDeleted()) +      return true; +    if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != +        AR_accessible) +      return true; + +    // -- a [virtual base class] B that cannot be [copied] because overload +    //    resolution, as applied to B's [copy] constructor, results in an +    //    ambiguity or a function that is deleted or inaccessible from the +    //    defaulted constructor +    CXXConstructorDecl *BaseCtor = LookupCopyConstructor(BaseDecl, ArgQuals); +    if (!BaseCtor || BaseCtor->isDeleted()) +      return true; +    if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(), PDiag()) != +        AR_accessible) +      return true; +  } + +  for (CXXRecordDecl::field_iterator FI = RD->field_begin(), +                                     FE = RD->field_end(); +       FI != FE; ++FI) { +    QualType FieldType = Context.getBaseElementType(FI->getType()); +     +    // -- for a copy constructor, a non-static data member of rvalue reference +    //    type +    if (FieldType->isRValueReferenceType()) +      return true; +  +    CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); + +    if (FieldRecord) { +      // This is an anonymous union +      if (FieldRecord->isUnion() && FieldRecord->isAnonymousStructOrUnion()) { +        // Anonymous unions inside unions do not variant members create +        if (!Union) { +          for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), +                                             UE = FieldRecord->field_end(); +               UI != UE; ++UI) { +            QualType UnionFieldType = Context.getBaseElementType(UI->getType()); +            CXXRecordDecl *UnionFieldRecord = +              UnionFieldType->getAsCXXRecordDecl(); + +            // -- a variant member with a non-trivial [copy] constructor and X +            //    is a union-like class +            if (UnionFieldRecord && +                !UnionFieldRecord->hasTrivialCopyConstructor()) +              return true; +          } +        } + +        // Don't try to initalize an anonymous union +        continue; +      } else { +         // -- a variant member with a non-trivial [copy] constructor and X is a +         //    union-like class +        if (Union && !FieldRecord->hasTrivialCopyConstructor()) +          return true; + +        // -- any [non-static data member] of a type with a destructor that is +        //    deleted or inaccessible from the defaulted constructor +        CXXDestructorDecl *FieldDtor = LookupDestructor(FieldRecord); +        if (FieldDtor->isDeleted()) +          return true; +        if (CheckDestructorAccess(Loc, FieldDtor, PDiag()) != +            AR_accessible) +          return true; +      } + +    // -- a [non-static data member of class type (or array thereof)] B that +    //    cannot be [copied] because overload resolution, as applied to B's +    //    [copy] constructor, results in an ambiguity or a function that is +    //    deleted or inaccessible from the defaulted constructor +      CXXConstructorDecl *FieldCtor = LookupCopyConstructor(FieldRecord, +                                                            ArgQuals); +      if (!FieldCtor || FieldCtor->isDeleted()) +        return true; +      if (CheckConstructorAccess(Loc, FieldCtor, FieldCtor->getAccess(), +                                 PDiag()) != AR_accessible) +        return true; +    } +  } + +  return false; +} + +bool Sema::ShouldDeleteCopyAssignmentOperator(CXXMethodDecl *MD) { +  CXXRecordDecl *RD = MD->getParent(); +  assert(!RD->isDependentType() && "do deletion after instantiation"); +  if (!LangOpts.CPlusPlus0x) +    return false; + +  SourceLocation Loc = MD->getLocation(); + +  // Do access control from the constructor +  ContextRAII MethodContext(*this, MD); + +  bool Union = RD->isUnion(); + +  bool ConstArg = +    MD->getParamDecl(0)->getType()->getPointeeType().isConstQualified(); + +  // We do this because we should never actually use an anonymous +  // union's constructor. +  if (Union && RD->isAnonymousStructOrUnion()) +    return false; + +  DeclarationName OperatorName = +    Context.DeclarationNames.getCXXOperatorName(OO_Equal); +  LookupResult R(*this, OperatorName, Loc, LookupOrdinaryName); +  R.suppressDiagnostics(); + +  // FIXME: We should put some diagnostic logic right into this function. + +  // C++0x [class.copy]/11 +  //    A defaulted [copy] assignment operator for class X is defined as deleted +  //    if X has: + +  for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), +                                          BE = RD->bases_end(); +       BI != BE; ++BI) { +    // We'll handle this one later +    if (BI->isVirtual()) +      continue; + +    QualType BaseType = BI->getType(); +    CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl(); +    assert(BaseDecl && "base isn't a CXXRecordDecl"); + +    // -- a [direct base class] B that cannot be [copied] because overload +    //    resolution, as applied to B's [copy] assignment operator, results in +    //    an ambiguity or a function that is deleted or inaccessible from the +    //    assignment operator + +    LookupQualifiedName(R, BaseDecl, false); + +    // Filter out any result that isn't a copy-assignment operator. +    LookupResult::Filter F = R.makeFilter(); +    while (F.hasNext()) { +      NamedDecl *D = F.next(); +      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) +        if (Method->isCopyAssignmentOperator()) +          continue; +       +      F.erase(); +    } +    F.done(); +  +    // Build a fake argument expression +    QualType ArgType = BaseType; +    QualType ThisType = BaseType; +    if (ConstArg) +      ArgType.addConst(); +    Expr *Args[] = { new (Context) OpaqueValueExpr(Loc, ThisType, VK_LValue) +                   , new (Context) OpaqueValueExpr(Loc, ArgType, VK_LValue) +                   }; + +    OverloadCandidateSet OCS((Loc)); +    OverloadCandidateSet::iterator Best; + +    AddFunctionCandidates(R.asUnresolvedSet(), Args, 2, OCS); + +    if (OCS.BestViableFunction(*this, Loc, Best, false) != +        OR_Success) +      return true; +  } + +  for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), +                                          BE = RD->vbases_end(); +       BI != BE; ++BI) { +    QualType BaseType = BI->getType(); +    CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl(); +    assert(BaseDecl && "base isn't a CXXRecordDecl"); + +    // -- a [virtual base class] B that cannot be [copied] because overload +    //    resolution, as applied to B's [copy] assignment operator, results in +    //    an ambiguity or a function that is deleted or inaccessible from the +    //    assignment operator + +    LookupQualifiedName(R, BaseDecl, false); + +    // Filter out any result that isn't a copy-assignment operator. +    LookupResult::Filter F = R.makeFilter(); +    while (F.hasNext()) { +      NamedDecl *D = F.next(); +      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) +        if (Method->isCopyAssignmentOperator()) +          continue; +       +      F.erase(); +    } +    F.done(); +  +    // Build a fake argument expression +    QualType ArgType = BaseType; +    QualType ThisType = BaseType; +    if (ConstArg) +      ArgType.addConst(); +    Expr *Args[] = { new (Context) OpaqueValueExpr(Loc, ThisType, VK_LValue) +                   , new (Context) OpaqueValueExpr(Loc, ArgType, VK_LValue) +                   }; + +    OverloadCandidateSet OCS((Loc)); +    OverloadCandidateSet::iterator Best; + +    AddFunctionCandidates(R.asUnresolvedSet(), Args, 2, OCS); + +    if (OCS.BestViableFunction(*this, Loc, Best, false) != +        OR_Success) +      return true; +  } + +  for (CXXRecordDecl::field_iterator FI = RD->field_begin(), +                                     FE = RD->field_end(); +       FI != FE; ++FI) { +    QualType FieldType = Context.getBaseElementType(FI->getType()); +     +    // -- a non-static data member of reference type +    if (FieldType->isReferenceType()) +      return true; + +    // -- a non-static data member of const non-class type (or array thereof) +    if (FieldType.isConstQualified() && !FieldType->isRecordType()) +      return true; +  +    CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); + +    if (FieldRecord) { +      // This is an anonymous union +      if (FieldRecord->isUnion() && FieldRecord->isAnonymousStructOrUnion()) { +        // Anonymous unions inside unions do not variant members create +        if (!Union) { +          for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), +                                             UE = FieldRecord->field_end(); +               UI != UE; ++UI) { +            QualType UnionFieldType = Context.getBaseElementType(UI->getType()); +            CXXRecordDecl *UnionFieldRecord = +              UnionFieldType->getAsCXXRecordDecl(); + +            // -- a variant member with a non-trivial [copy] assignment operator +            //    and X is a union-like class +            if (UnionFieldRecord && +                !UnionFieldRecord->hasTrivialCopyAssignment()) +              return true; +          } +        } + +        // Don't try to initalize an anonymous union +        continue; +      // -- a variant member with a non-trivial [copy] assignment operator +      //    and X is a union-like class +      } else if (Union && !FieldRecord->hasTrivialCopyAssignment()) { +          return true; +      } + +      LookupQualifiedName(R, FieldRecord, false); + +      // Filter out any result that isn't a copy-assignment operator. +      LookupResult::Filter F = R.makeFilter(); +      while (F.hasNext()) { +        NamedDecl *D = F.next(); +        if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) +          if (Method->isCopyAssignmentOperator()) +            continue; +         +        F.erase(); +      } +      F.done(); +    +      // Build a fake argument expression +      QualType ArgType = FieldType; +      QualType ThisType = FieldType; +      if (ConstArg) +        ArgType.addConst(); +      Expr *Args[] = { new (Context) OpaqueValueExpr(Loc, ThisType, VK_LValue) +                     , new (Context) OpaqueValueExpr(Loc, ArgType, VK_LValue) +                     }; + +      OverloadCandidateSet OCS((Loc)); +      OverloadCandidateSet::iterator Best; + +      AddFunctionCandidates(R.asUnresolvedSet(), Args, 2, OCS); + +      if (OCS.BestViableFunction(*this, Loc, Best, false) != +          OR_Success) +        return true; +    } +  } + +  return false; +} + +bool Sema::ShouldDeleteDestructor(CXXDestructorDecl *DD) { +  CXXRecordDecl *RD = DD->getParent(); +  assert(!RD->isDependentType() && "do deletion after instantiation"); +  if (!LangOpts.CPlusPlus0x) +    return false; + +  SourceLocation Loc = DD->getLocation(); + +  // Do access control from the destructor +  ContextRAII CtorContext(*this, DD); + +  bool Union = RD->isUnion(); + +  // We do this because we should never actually use an anonymous +  // union's destructor. +  if (Union && RD->isAnonymousStructOrUnion()) +    return false; + +  // C++0x [class.dtor]p5 +  //    A defaulted destructor for a class X is defined as deleted if: +  for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), +                                          BE = RD->bases_end(); +       BI != BE; ++BI) { +    // We'll handle this one later +    if (BI->isVirtual()) +      continue; + +    CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); +    CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); +    assert(BaseDtor && "base has no destructor"); + +    // -- any direct or virtual base class has a deleted destructor or +    //    a destructor that is inaccessible from the defaulted destructor +    if (BaseDtor->isDeleted()) +      return true; +    if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != +        AR_accessible) +      return true; +  } + +  for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), +                                          BE = RD->vbases_end(); +       BI != BE; ++BI) { +    CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); +    CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); +    assert(BaseDtor && "base has no destructor"); + +    // -- any direct or virtual base class has a deleted destructor or +    //    a destructor that is inaccessible from the defaulted destructor +    if (BaseDtor->isDeleted()) +      return true; +    if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != +        AR_accessible) +      return true; +  } + +  for (CXXRecordDecl::field_iterator FI = RD->field_begin(), +                                     FE = RD->field_end(); +       FI != FE; ++FI) { +    QualType FieldType = Context.getBaseElementType(FI->getType()); +    CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); +    if (FieldRecord) { +      if (FieldRecord->isUnion() && FieldRecord->isAnonymousStructOrUnion()) { +         for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), +                                            UE = FieldRecord->field_end(); +              UI != UE; ++UI) { +           QualType UnionFieldType = Context.getBaseElementType(FI->getType()); +           CXXRecordDecl *UnionFieldRecord = +             UnionFieldType->getAsCXXRecordDecl(); + +           // -- X is a union-like class that has a variant member with a non- +           //    trivial destructor. +           if (UnionFieldRecord && !UnionFieldRecord->hasTrivialDestructor()) +             return true; +         } +      // Technically we are supposed to do this next check unconditionally. +      // But that makes absolutely no sense. +      } else { +        CXXDestructorDecl *FieldDtor = LookupDestructor(FieldRecord); + +        // -- any of the non-static data members has class type M (or array +        //    thereof) and M has a deleted destructor or a destructor that is +        //    inaccessible from the defaulted destructor +        if (FieldDtor->isDeleted()) +          return true; +        if (CheckDestructorAccess(Loc, FieldDtor, PDiag()) != +          AR_accessible) +        return true; +         +        // -- X is a union-like class that has a variant member with a non- +        //    trivial destructor. +        if (Union && !FieldDtor->isTrivial()) +          return true; +      } +    } +  } + +  if (DD->isVirtual()) { +    FunctionDecl *OperatorDelete = 0; +    DeclarationName Name = +      Context.DeclarationNames.getCXXOperatorName(OO_Delete); +    if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete, +          false)) +      return true; +  } + + +  return false;  }  /// \brief Data used with FindHiddenVirtualMethod @@ -3053,113 +4169,6 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,                          dyn_cast_or_null<CXXRecordDecl>(TagDecl));  } -namespace { -  /// \brief Helper class that collects exception specifications for  -  /// implicitly-declared special member functions. -  class ImplicitExceptionSpecification { -    ASTContext &Context; -    // We order exception specifications thus: -    // noexcept is the most restrictive, but is only used in C++0x. -    // throw() comes next. -    // Then a throw(collected exceptions) -    // Finally no specification. -    // throw(...) is used instead if any called function uses it. -    ExceptionSpecificationType ComputedEST; -    llvm::SmallPtrSet<CanQualType, 4> ExceptionsSeen; -    llvm::SmallVector<QualType, 4> Exceptions; - -    void ClearExceptions() { -      ExceptionsSeen.clear(); -      Exceptions.clear(); -    } - -  public: -    explicit ImplicitExceptionSpecification(ASTContext &Context)  -      : Context(Context), ComputedEST(EST_BasicNoexcept) { -      if (!Context.getLangOptions().CPlusPlus0x) -        ComputedEST = EST_DynamicNone; -    } - -    /// \brief Get the computed exception specification type. -    ExceptionSpecificationType getExceptionSpecType() const { -      assert(ComputedEST != EST_ComputedNoexcept && -             "noexcept(expr) should not be a possible result"); -      return ComputedEST; -    } - -    /// \brief The number of exceptions in the exception specification. -    unsigned size() const { return Exceptions.size(); } - -    /// \brief The set of exceptions in the exception specification. -    const QualType *data() const { return Exceptions.data(); } - -    /// \brief Integrate another called method into the collected data. -    void CalledDecl(CXXMethodDecl *Method) { -      // If we have an MSAny spec already, don't bother. -      if (!Method || ComputedEST == EST_MSAny) -        return; - -      const FunctionProtoType *Proto -        = Method->getType()->getAs<FunctionProtoType>(); - -      ExceptionSpecificationType EST = Proto->getExceptionSpecType(); - -      // If this function can throw any exceptions, make a note of that. -      if (EST == EST_MSAny || EST == EST_None) { -        ClearExceptions(); -        ComputedEST = EST; -        return; -      } - -      // If this function has a basic noexcept, it doesn't affect the outcome. -      if (EST == EST_BasicNoexcept) -        return; - -      // If we have a throw-all spec at this point, ignore the function. -      if (ComputedEST == EST_None) -        return; - -      // If we're still at noexcept(true) and there's a nothrow() callee, -      // change to that specification. -      if (EST == EST_DynamicNone) { -        if (ComputedEST == EST_BasicNoexcept) -          ComputedEST = EST_DynamicNone; -        return; -      } - -      // Check out noexcept specs. -      if (EST == EST_ComputedNoexcept) { -        FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(Context); -        assert(NR != FunctionProtoType::NR_NoNoexcept && -               "Must have noexcept result for EST_ComputedNoexcept."); -        assert(NR != FunctionProtoType::NR_Dependent && -               "Should not generate implicit declarations for dependent cases, " -               "and don't know how to handle them anyway."); - -        // noexcept(false) -> no spec on the new function -        if (NR == FunctionProtoType::NR_Throw) { -          ClearExceptions(); -          ComputedEST = EST_None; -        } -        // noexcept(true) won't change anything either. -        return; -      } - -      assert(EST == EST_Dynamic && "EST case not considered earlier."); -      assert(ComputedEST != EST_None && -             "Shouldn't collect exceptions when throw-all is guaranteed."); -      ComputedEST = EST_Dynamic; -      // Record the exceptions in this function's exception specification. -      for (FunctionProtoType::exception_iterator E = Proto->exception_begin(), -                                              EEnd = Proto->exception_end(); -           E != EEnd; ++E) -        if (ExceptionsSeen.insert(Context.getCanonicalType(*E))) -          Exceptions.push_back(*E); -    } -  }; -} - -  /// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared  /// special functions, such as the default constructor, copy  /// constructor, or destructor, to the given C++ class (C++ @@ -3467,6 +4476,11 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,    if (const TypedefType *TT = DeclaratorType->getAs<TypedefType>())      Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)        << DeclaratorType << isa<TypeAliasDecl>(TT->getDecl()); +  else if (const TemplateSpecializationType *TST = +             DeclaratorType->getAs<TemplateSpecializationType>()) +    if (TST->isTypeAlias()) +      Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) +        << DeclaratorType << 1;    // C++ [class.dtor]p2:    //   A destructor is used to destroy objects of its class type. A @@ -3725,18 +4739,37 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,      //   treated as an original-namespace-name.      //      // Since namespace names are unique in their scope, and we don't -    // look through using directives, just -    DeclContext::lookup_result R = CurContext->getRedeclContext()->lookup(II); -    NamedDecl *PrevDecl = R.first == R.second? 0 : *R.first; - +    // look through using directives, just look for any ordinary names. +     +    const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member |  +      Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag |  +      Decl::IDNS_Namespace; +    NamedDecl *PrevDecl = 0; +    for (DeclContext::lookup_result R  +            = CurContext->getRedeclContext()->lookup(II); +         R.first != R.second; ++R.first) { +      if ((*R.first)->getIdentifierNamespace() & IDNS) { +        PrevDecl = *R.first; +        break; +      } +    } +          if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) {        // This is an extended namespace definition.        if (Namespc->isInline() != OrigNS->isInline()) {          // inline-ness must match -        Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch) -          << Namespc->isInline(); +        if (OrigNS->isInline()) { +          // The user probably just forgot the 'inline', so suggest that it +          // be added back. +          Diag(Namespc->getLocation(),  +               diag::warn_inline_namespace_reopened_noninline) +            << FixItHint::CreateInsertion(NamespaceLoc, "inline "); +        } else { +          Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch) +            << Namespc->isInline(); +        }          Diag(OrigNS->getLocation(), diag::note_previous_definition); -        Namespc->setInvalidDecl(); +          // Recover by ignoring the new namespace's inline status.          Namespc->setInline(OrigNS->isInline());        } @@ -4408,6 +5441,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,    // Otherwise, look up the target name.    LookupResult R(*this, NameInfo, LookupOrdinaryName); +  R.setUsingDeclaration(true);    // Unlike most lookups, we don't always want to hide tag    // declarations: tag names are visible through the using declaration @@ -4701,9 +5735,13 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,  Decl *Sema::ActOnAliasDeclaration(Scope *S,                                    AccessSpecifier AS, +                                  MultiTemplateParamsArg TemplateParamLists,                                    SourceLocation UsingLoc,                                    UnqualifiedId &Name,                                    TypeResult Type) { +  // Skip up to the relevant declaration scope. +  while (S->getFlags() & Scope::TemplateParamScope) +    S = S->getParent();    assert((S->getFlags() & Scope::DeclScope) &&           "got alias-declaration outside of declaration scope"); @@ -4719,8 +5757,11 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,      return 0;    if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo, -                                      UPPC_DeclarationType)) +                                      UPPC_DeclarationType)) {      Invalid = true; +    TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy,  +                                             TInfo->getTypeLoc().getBeginLoc()); +  }    LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration);    LookupName(Previous, S); @@ -4745,13 +5786,93 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,    if (Invalid)      NewTD->setInvalidDecl(); +  CheckTypedefForVariablyModifiedType(S, NewTD); +  Invalid |= NewTD->isInvalidDecl(); +    bool Redeclaration = false; -  ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration); + +  NamedDecl *NewND; +  if (TemplateParamLists.size()) { +    TypeAliasTemplateDecl *OldDecl = 0; +    TemplateParameterList *OldTemplateParams = 0; + +    if (TemplateParamLists.size() != 1) { +      Diag(UsingLoc, diag::err_alias_template_extra_headers) +        << SourceRange(TemplateParamLists.get()[1]->getTemplateLoc(), +         TemplateParamLists.get()[TemplateParamLists.size()-1]->getRAngleLoc()); +    } +    TemplateParameterList *TemplateParams = TemplateParamLists.get()[0]; + +    // Only consider previous declarations in the same scope. +    FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage*/false, +                         /*ExplicitInstantiationOrSpecialization*/false); +    if (!Previous.empty()) { +      Redeclaration = true; + +      OldDecl = Previous.getAsSingle<TypeAliasTemplateDecl>(); +      if (!OldDecl && !Invalid) { +        Diag(UsingLoc, diag::err_redefinition_different_kind) +          << Name.Identifier; + +        NamedDecl *OldD = Previous.getRepresentativeDecl(); +        if (OldD->getLocation().isValid()) +          Diag(OldD->getLocation(), diag::note_previous_definition); + +        Invalid = true; +      } + +      if (!Invalid && OldDecl && !OldDecl->isInvalidDecl()) { +        if (TemplateParameterListsAreEqual(TemplateParams, +                                           OldDecl->getTemplateParameters(), +                                           /*Complain=*/true, +                                           TPL_TemplateMatch)) +          OldTemplateParams = OldDecl->getTemplateParameters(); +        else +          Invalid = true; + +        TypeAliasDecl *OldTD = OldDecl->getTemplatedDecl(); +        if (!Invalid && +            !Context.hasSameType(OldTD->getUnderlyingType(), +                                 NewTD->getUnderlyingType())) { +          // FIXME: The C++0x standard does not clearly say this is ill-formed, +          // but we can't reasonably accept it. +          Diag(NewTD->getLocation(), diag::err_redefinition_different_typedef) +            << 2 << NewTD->getUnderlyingType() << OldTD->getUnderlyingType(); +          if (OldTD->getLocation().isValid()) +            Diag(OldTD->getLocation(), diag::note_previous_definition); +          Invalid = true; +        } +      } +    } + +    // Merge any previous default template arguments into our parameters, +    // and check the parameter list. +    if (CheckTemplateParameterList(TemplateParams, OldTemplateParams, +                                   TPC_TypeAliasTemplate)) +      return 0; + +    TypeAliasTemplateDecl *NewDecl = +      TypeAliasTemplateDecl::Create(Context, CurContext, UsingLoc, +                                    Name.Identifier, TemplateParams, +                                    NewTD); + +    NewDecl->setAccess(AS); + +    if (Invalid) +      NewDecl->setInvalidDecl(); +    else if (OldDecl) +      NewDecl->setPreviousDeclaration(OldDecl); + +    NewND = NewDecl; +  } else { +    ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration); +    NewND = NewTD; +  }    if (!Redeclaration) -    PushOnScopeChains(NewTD, S); +    PushOnScopeChains(NewND, S); -  return NewTD; +  return NewND;  }  Decl *Sema::ActOnNamespaceAliasDef(Scope *S, @@ -4855,39 +5976,8 @@ namespace {    };  } -static CXXConstructorDecl *getDefaultConstructorUnsafe(Sema &Self, -                                                       CXXRecordDecl *D) { -  ASTContext &Context = Self.Context; -  QualType ClassType = Context.getTypeDeclType(D); -  DeclarationName ConstructorName -    = Context.DeclarationNames.getCXXConstructorName( -                      Context.getCanonicalType(ClassType.getUnqualifiedType())); - -  DeclContext::lookup_const_iterator Con, ConEnd; -  for (llvm::tie(Con, ConEnd) = D->lookup(ConstructorName); -       Con != ConEnd; ++Con) { -    // FIXME: In C++0x, a constructor template can be a default constructor. -    if (isa<FunctionTemplateDecl>(*Con)) -      continue; - -    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); -    if (Constructor->isDefaultConstructor()) -      return Constructor; -  } -  return 0; -} - -CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( -                                                     CXXRecordDecl *ClassDecl) { -  // C++ [class.ctor]p5: -  //   A default constructor for a class X is a constructor of class X -  //   that can be called without an argument. If there is no -  //   user-declared constructor for class X, a default constructor is -  //   implicitly declared. An implicitly-declared default constructor -  //   is an inline public member of its class. -  assert(!ClassDecl->hasUserDeclaredConstructor() &&  -         "Should not build implicit default constructor!"); -   +Sema::ImplicitExceptionSpecification +Sema::ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl) {    // C++ [except.spec]p14:    //   An implicitly declared special member function (Clause 12) shall have an     //   exception-specification. [...] @@ -4902,10 +5992,10 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(      if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {        CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); -      if (!BaseClassDecl->hasDeclaredDefaultConstructor()) -        ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl)); -      else if (CXXConstructorDecl *Constructor -                            = getDefaultConstructorUnsafe(*this, BaseClassDecl)) +      CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl); +      // If this is a deleted function, add it anyway. This might be conformant +      // with the standard. This might not. I'm not sure. It might not matter. +      if (Constructor)          ExceptSpec.CalledDecl(Constructor);      }    } @@ -4916,10 +6006,10 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(         B != BEnd; ++B) {      if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {        CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); -      if (!BaseClassDecl->hasDeclaredDefaultConstructor()) -        ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl)); -      else if (CXXConstructorDecl *Constructor -                            = getDefaultConstructorUnsafe(*this, BaseClassDecl)) +      CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl); +      // If this is a deleted function, add it anyway. This might be conformant +      // with the standard. This might not. I'm not sure. It might not matter. +      if (Constructor)          ExceptSpec.CalledDecl(Constructor);      }    } @@ -4928,22 +6018,42 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(    for (RecordDecl::field_iterator F = ClassDecl->field_begin(),                                 FEnd = ClassDecl->field_end();         F != FEnd; ++F) { -    if (const RecordType *RecordTy +    if (F->hasInClassInitializer()) { +      if (Expr *E = F->getInClassInitializer()) +        ExceptSpec.CalledExpr(E); +      else if (!F->isInvalidDecl()) +        ExceptSpec.SetDelayed(); +    } else if (const RecordType *RecordTy                = Context.getBaseElementType(F->getType())->getAs<RecordType>()) { -      CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); -      if (!FieldClassDecl->hasDeclaredDefaultConstructor()) -        ExceptSpec.CalledDecl( -                            DeclareImplicitDefaultConstructor(FieldClassDecl)); -      else if (CXXConstructorDecl *Constructor -                           = getDefaultConstructorUnsafe(*this, FieldClassDecl)) +      CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); +      CXXConstructorDecl *Constructor = LookupDefaultConstructor(FieldRecDecl); +      // If this is a deleted function, add it anyway. This might be conformant +      // with the standard. This might not. I'm not sure. It might not matter. +      // In particular, the problem is that this function never gets called. It +      // might just be ill-formed because this function attempts to refer to +      // a deleted function here. +      if (Constructor)          ExceptSpec.CalledDecl(Constructor);      }    } -  FunctionProtoType::ExtProtoInfo EPI; -  EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType(); -  EPI.NumExceptions = ExceptSpec.size(); -  EPI.Exceptions = ExceptSpec.data(); +  return ExceptSpec; +} + +CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( +                                                     CXXRecordDecl *ClassDecl) { +  // C++ [class.ctor]p5: +  //   A default constructor for a class X is a constructor of class X +  //   that can be called without an argument. If there is no +  //   user-declared constructor for class X, a default constructor is +  //   implicitly declared. An implicitly-declared default constructor +  //   is an inline public member of its class. +  assert(!ClassDecl->hasUserDeclaredConstructor() &&  +         "Should not build implicit default constructor!"); + +  ImplicitExceptionSpecification Spec =  +    ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl); +  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();    // Create the actual constructor declaration.    CanQualType ClassType @@ -4961,8 +6071,9 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(                                   /*isInline=*/true,                                   /*isImplicitlyDeclared=*/true);    DefaultCon->setAccess(AS_public); +  DefaultCon->setDefaulted();    DefaultCon->setImplicit(); -  DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor()); +  DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor());    // Note that we have declared this constructor.    ++ASTContext::NumImplicitDefaultConstructorsDeclared; @@ -4970,14 +6081,18 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(    if (Scope *S = getScopeForContext(ClassDecl))      PushOnScopeChains(DefaultCon, S, false);    ClassDecl->addDecl(DefaultCon); + +  if (ShouldDeleteDefaultConstructor(DefaultCon)) +    DefaultCon->setDeletedAsWritten();    return DefaultCon;  }  void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,                                              CXXConstructorDecl *Constructor) { -  assert((Constructor->isImplicit() && Constructor->isDefaultConstructor() && -          !Constructor->isUsed(false)) && +  assert((Constructor->isDefaulted() && Constructor->isDefaultConstructor() && +          !Constructor->doesThisDeclarationHaveABody() && +          !Constructor->isDeleted()) &&      "DefineImplicitDefaultConstructor - call it for implicit default ctor");    CXXRecordDecl *ClassDecl = Constructor->getParent(); @@ -4988,7 +6103,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,    if (SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false) ||        Trap.hasErrorOccurred()) {      Diag(CurrentLocation, diag::note_member_synthesized_at)  -      << CXXConstructor << Context.getTagDeclType(ClassDecl); +      << CXXDefaultConstructor << Context.getTagDeclType(ClassDecl);      Constructor->setInvalidDecl();      return;    } @@ -5004,6 +6119,59 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,    }  } +/// Get any existing defaulted default constructor for the given class. Do not +/// implicitly define one if it does not exist. +static CXXConstructorDecl *getDefaultedDefaultConstructorUnsafe(Sema &Self, +                                                             CXXRecordDecl *D) { +  ASTContext &Context = Self.Context; +  QualType ClassType = Context.getTypeDeclType(D); +  DeclarationName ConstructorName +    = Context.DeclarationNames.getCXXConstructorName( +                      Context.getCanonicalType(ClassType.getUnqualifiedType())); + +  DeclContext::lookup_const_iterator Con, ConEnd; +  for (llvm::tie(Con, ConEnd) = D->lookup(ConstructorName); +       Con != ConEnd; ++Con) { +    // A function template cannot be defaulted. +    if (isa<FunctionTemplateDecl>(*Con)) +      continue; + +    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); +    if (Constructor->isDefaultConstructor()) +      return Constructor->isDefaulted() ? Constructor : 0; +  } +  return 0; +} + +void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) { +  if (!D) return; +  AdjustDeclIfTemplate(D); + +  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(D); +  CXXConstructorDecl *CtorDecl +    = getDefaultedDefaultConstructorUnsafe(*this, ClassDecl); + +  if (!CtorDecl) return; + +  // Compute the exception specification for the default constructor. +  const FunctionProtoType *CtorTy = +    CtorDecl->getType()->castAs<FunctionProtoType>(); +  if (CtorTy->getExceptionSpecType() == EST_Delayed) { +    ImplicitExceptionSpecification Spec =  +      ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl); +    FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); +    assert(EPI.ExceptionSpecType != EST_Delayed); + +    CtorDecl->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); +  } + +  // If the default constructor is explicitly defaulted, checking the exception +  // specification is deferred until now. +  if (!CtorDecl->isInvalidDecl() && CtorDecl->isExplicitlyDefaulted() && +      !ClassDecl->isDependentType()) +    CheckExplicitlyDefaultedDefaultConstructor(CtorDecl); +} +  void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {    // We start with an initial pass over the base classes to collect those that    // inherit constructors from. If there are none, we can forgo all further @@ -5097,7 +6265,9 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {          // Build up a function type for this particular constructor.          // FIXME: The working paper does not consider that the exception spec          // for the inheriting constructor might be larger than that of the -        // source. This code doesn't yet, either. +        // source. This code doesn't yet, either. When it does, this code will +        // need to be delayed until after exception specifications and in-class +        // member initializers are attached.          const Type *NewCtorType;          if (params == maxParams)            NewCtorType = BaseCtorType; @@ -5179,12 +6349,8 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {    }  } -CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { -  // C++ [class.dtor]p2: -  //   If a class has no user-declared destructor, a destructor is -  //   declared implicitly. An implicitly-declared destructor is an -  //   inline public member of its class. -   +Sema::ImplicitExceptionSpecification +Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) {    // C++ [except.spec]p14:     //   An implicitly declared special member function (Clause 12) shall have     //   an exception-specification. @@ -5199,18 +6365,18 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {      if (const RecordType *BaseType = B->getType()->getAs<RecordType>())        ExceptSpec.CalledDecl( -                    LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl()))); +                   LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));    } -   +    // Virtual base-class destructors.    for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),                                         BEnd = ClassDecl->vbases_end();         B != BEnd; ++B) {      if (const RecordType *BaseType = B->getType()->getAs<RecordType>())        ExceptSpec.CalledDecl( -                    LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl()))); +                  LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));    } -   +    // Field destructors.    for (RecordDecl::field_iterator F = ClassDecl->field_begin(),                                 FEnd = ClassDecl->field_end(); @@ -5218,14 +6384,23 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {      if (const RecordType *RecordTy          = Context.getBaseElementType(F->getType())->getAs<RecordType>())        ExceptSpec.CalledDecl( -                    LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl()))); +                  LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));    } +  return ExceptSpec; +} + +CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { +  // C++ [class.dtor]p2: +  //   If a class has no user-declared destructor, a destructor is +  //   declared implicitly. An implicitly-declared destructor is an +  //   inline public member of its class. +   +  ImplicitExceptionSpecification Spec = +      ComputeDefaultedDtorExceptionSpec(ClassDecl);  +  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); +    // Create the actual destructor declaration. -  FunctionProtoType::ExtProtoInfo EPI; -  EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType(); -  EPI.NumExceptions = ExceptSpec.size(); -  EPI.Exceptions = ExceptSpec.data();    QualType Ty = Context.getFunctionType(Context.VoidTy, 0, 0, EPI);    CanQualType ClassType @@ -5239,6 +6414,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {                                    /*isInline=*/true,                                    /*isImplicitlyDeclared=*/true);    Destructor->setAccess(AS_public); +  Destructor->setDefaulted();    Destructor->setImplicit();    Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); @@ -5252,6 +6428,9 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {    // This could be uniqued if it ever proves significant.    Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty)); + +  if (ShouldDeleteDestructor(Destructor)) +    Destructor->setDeletedAsWritten();    AddOverriddenMethods(ClassDecl, Destructor); @@ -5260,7 +6439,8 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {  void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,                                      CXXDestructorDecl *Destructor) { -  assert((Destructor->isImplicit() && !Destructor->isUsed(false)) && +  assert((Destructor->isDefaulted() && +          !Destructor->doesThisDeclarationHaveABody()) &&           "DefineImplicitDestructor - call it for implicit default dtor");    CXXRecordDecl *ClassDecl = Destructor->getParent();    assert(ClassDecl && "DefineImplicitDestructor - invalid destructor"); @@ -5293,6 +6473,35 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,    }  } +void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *classDecl, +                                         CXXDestructorDecl *destructor) { +  // C++11 [class.dtor]p3: +  //   A declaration of a destructor that does not have an exception- +  //   specification is implicitly considered to have the same exception- +  //   specification as an implicit declaration. +  const FunctionProtoType *dtorType = destructor->getType()-> +                                        getAs<FunctionProtoType>(); +  if (dtorType->hasExceptionSpec()) +    return; + +  ImplicitExceptionSpecification exceptSpec = +      ComputeDefaultedDtorExceptionSpec(classDecl); + +  // Replace the destructor's type. +  FunctionProtoType::ExtProtoInfo epi; +  epi.ExceptionSpecType = exceptSpec.getExceptionSpecType(); +  epi.NumExceptions = exceptSpec.size(); +  epi.Exceptions = exceptSpec.data(); +  QualType ty = Context.getFunctionType(Context.VoidTy, 0, 0, epi); + +  destructor->setType(ty); + +  // FIXME: If the destructor has a body that could throw, and the newly created +  // spec doesn't allow exceptions, we should emit a warning, because this +  // change in behavior can break conforming C++03 programs at runtime. +  // However, we don't have a body yet, so it needs to be done somewhere else. +} +  /// \brief Builds a statement that copies the given entity from \p From to  /// \c To.  /// @@ -5530,13 +6739,9 @@ static bool hasConstCopyAssignment(Sema &S, const CXXRecordDecl *CClass) {    return false;    } -CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { -  // Note: The following rules are largely analoguous to the copy -  // constructor rules. Note that virtual bases are not taken into account -  // for determining the argument type of the operator. Note also that -  // operators taking an object instead of a reference are allowed. -   -   +std::pair<Sema::ImplicitExceptionSpecification, bool> +Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst( +                                                   CXXRecordDecl *ClassDecl) {    // C++ [class.copy]p10:    //   If the class definition does not explicitly declare a copy    //   assignment operator, one is declared implicitly. @@ -5581,11 +6786,6 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {    //   have the form    //    //       X& X::operator=(X&) -  QualType ArgType = Context.getTypeDeclType(ClassDecl); -  QualType RetType = Context.getLValueReferenceType(ArgType); -  if (HasConstCopyAssignment) -    ArgType = ArgType.withConst(); -  ArgType = Context.getLValueReferenceType(ArgType);    // C++ [except.spec]p14:    //   An implicitly declared special member function (Clause 12) shall have an  @@ -5622,12 +6822,29 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {      }          } +  return std::make_pair(ExceptSpec, HasConstCopyAssignment); +} + +CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { +  // Note: The following rules are largely analoguous to the copy +  // constructor rules. Note that virtual bases are not taken into account +  // for determining the argument type of the operator. Note also that +  // operators taking an object instead of a reference are allowed. + +  ImplicitExceptionSpecification Spec(Context); +  bool Const; +  llvm::tie(Spec, Const) = +    ComputeDefaultedCopyAssignmentExceptionSpecAndConst(ClassDecl); + +  QualType ArgType = Context.getTypeDeclType(ClassDecl); +  QualType RetType = Context.getLValueReferenceType(ArgType); +  if (Const) +    ArgType = ArgType.withConst(); +  ArgType = Context.getLValueReferenceType(ArgType); +    //   An implicitly-declared copy assignment operator is an inline public    //   member of its class. -  FunctionProtoType::ExtProtoInfo EPI; -  EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType(); -  EPI.NumExceptions = ExceptSpec.size(); -  EPI.Exceptions = ExceptSpec.data(); +  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();    DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);    SourceLocation ClassLoc = ClassDecl->getLocation();    DeclarationNameInfo NameInfo(Name, ClassLoc); @@ -5639,6 +6856,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {                              /*isInline=*/true,                              SourceLocation());    CopyAssignment->setAccess(AS_public); +  CopyAssignment->setDefaulted();    CopyAssignment->setImplicit();    CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment()); @@ -5652,21 +6870,24 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {    // Note that we have added this copy-assignment operator.    ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; -   +    if (Scope *S = getScopeForContext(ClassDecl))      PushOnScopeChains(CopyAssignment, S, false);    ClassDecl->addDecl(CopyAssignment); +  if (ShouldDeleteCopyAssignmentOperator(CopyAssignment)) +    CopyAssignment->setDeletedAsWritten(); +      AddOverriddenMethods(ClassDecl, CopyAssignment);    return CopyAssignment;  }  void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,                                          CXXMethodDecl *CopyAssignOperator) { -  assert((CopyAssignOperator->isImplicit() &&  +  assert((CopyAssignOperator->isDefaulted() &&             CopyAssignOperator->isOverloadedOperator() &&            CopyAssignOperator->getOverloadedOperator() == OO_Equal && -          !CopyAssignOperator->isUsed(false)) && +          !CopyAssignOperator->doesThisDeclarationHaveABody()) &&           "DefineImplicitCopyAssignment called for wrong function");    CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent(); @@ -5956,12 +7177,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,    }  } -CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( -                                                    CXXRecordDecl *ClassDecl) { -  // C++ [class.copy]p4: -  //   If the class definition does not explicitly declare a copy -  //   constructor, one is declared implicitly. -   +std::pair<Sema::ImplicitExceptionSpecification, bool> +Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {    // C++ [class.copy]p5:    //   The implicitly-declared copy constructor for a class X will    //   have the form @@ -5969,6 +7186,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(    //       X::X(const X&)    //    //   if +  // FIXME: It ought to be possible to store this on the record.    bool HasConstCopyConstructor = true;    //     -- each direct or virtual base class B of X has a copy @@ -5984,11 +7202,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(      CXXRecordDecl *BaseClassDecl        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); -    if (!BaseClassDecl->hasDeclaredCopyConstructor()) -      DeclareImplicitCopyConstructor(BaseClassDecl); -   -    HasConstCopyConstructor -      = BaseClassDecl->hasConstCopyConstructor(Context); +    LookupCopyConstructor(BaseClassDecl, Qualifiers::Const, +                          &HasConstCopyConstructor);    }    for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), @@ -5997,11 +7212,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(         ++Base) {      CXXRecordDecl *BaseClassDecl        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); -    if (!BaseClassDecl->hasDeclaredCopyConstructor()) -      DeclareImplicitCopyConstructor(BaseClassDecl); -     -    HasConstCopyConstructor -      = BaseClassDecl->hasConstCopyConstructor(Context); +    LookupCopyConstructor(BaseClassDecl, Qualifiers::Const, +                          &HasConstCopyConstructor);    }    //     -- for all the nonstatic data members of X that are of a @@ -6013,27 +7225,16 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(         HasConstCopyConstructor && Field != FieldEnd;         ++Field) {      QualType FieldType = Context.getBaseElementType((*Field)->getType()); -    if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { -      CXXRecordDecl *FieldClassDecl -        = cast<CXXRecordDecl>(FieldClassType->getDecl()); -      if (!FieldClassDecl->hasDeclaredCopyConstructor()) -        DeclareImplicitCopyConstructor(FieldClassDecl); - -      HasConstCopyConstructor -        = FieldClassDecl->hasConstCopyConstructor(Context); +    if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { +      LookupCopyConstructor(FieldClassDecl, Qualifiers::Const, +                            &HasConstCopyConstructor);      }    } -      //   Otherwise, the implicitly declared copy constructor will have    //   the form    //    //       X::X(X&) -  QualType ClassType = Context.getTypeDeclType(ClassDecl); -  QualType ArgType = ClassType; -  if (HasConstCopyConstructor) -    ArgType = ArgType.withConst(); -  ArgType = Context.getLValueReferenceType(ArgType); -   +     // C++ [except.spec]p14:    //   An implicitly declared special member function (Clause 12) shall have an     //   exception-specification. [...] @@ -6049,11 +7250,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(      CXXRecordDecl *BaseClassDecl        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); -    if (!BaseClassDecl->hasDeclaredCopyConstructor()) -      DeclareImplicitCopyConstructor(BaseClassDecl); - -    if (CXXConstructorDecl *CopyConstructor -                          = BaseClassDecl->getCopyConstructor(Context, Quals)) +    if (CXXConstructorDecl *CopyConstructor = +          LookupCopyConstructor(BaseClassDecl, Quals))        ExceptSpec.CalledDecl(CopyConstructor);    }    for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), @@ -6062,11 +7260,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(         ++Base) {      CXXRecordDecl *BaseClassDecl        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); -    if (!BaseClassDecl->hasDeclaredCopyConstructor()) -      DeclareImplicitCopyConstructor(BaseClassDecl); - -    if (CXXConstructorDecl *CopyConstructor -                          = BaseClassDecl->getCopyConstructor(Context, Quals)) +    if (CXXConstructorDecl *CopyConstructor = +          LookupCopyConstructor(BaseClassDecl, Quals))        ExceptSpec.CalledDecl(CopyConstructor);    }    for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), @@ -6074,29 +7269,43 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(         Field != FieldEnd;         ++Field) {      QualType FieldType = Context.getBaseElementType((*Field)->getType()); -    if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { -      CXXRecordDecl *FieldClassDecl -        = cast<CXXRecordDecl>(FieldClassType->getDecl()); -      if (!FieldClassDecl->hasDeclaredCopyConstructor()) -        DeclareImplicitCopyConstructor(FieldClassDecl); - -      if (CXXConstructorDecl *CopyConstructor -                          = FieldClassDecl->getCopyConstructor(Context, Quals)) -        ExceptSpec.CalledDecl(CopyConstructor); +    if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { +      if (CXXConstructorDecl *CopyConstructor = +        LookupCopyConstructor(FieldClassDecl, Quals)) +      ExceptSpec.CalledDecl(CopyConstructor);      }    } -  //   An implicitly-declared copy constructor is an inline public -  //   member of its class. -  FunctionProtoType::ExtProtoInfo EPI; -  EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType(); -  EPI.NumExceptions = ExceptSpec.size(); -  EPI.Exceptions = ExceptSpec.data(); +  return std::make_pair(ExceptSpec, HasConstCopyConstructor); +} + +CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( +                                                    CXXRecordDecl *ClassDecl) { +  // C++ [class.copy]p4: +  //   If the class definition does not explicitly declare a copy +  //   constructor, one is declared implicitly. + +  ImplicitExceptionSpecification Spec(Context); +  bool Const; +  llvm::tie(Spec, Const) = +    ComputeDefaultedCopyCtorExceptionSpecAndConst(ClassDecl); + +  QualType ClassType = Context.getTypeDeclType(ClassDecl); +  QualType ArgType = ClassType; +  if (Const) +    ArgType = ArgType.withConst(); +  ArgType = Context.getLValueReferenceType(ArgType); +  +  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); +    DeclarationName Name      = Context.DeclarationNames.getCXXConstructorName(                                             Context.getCanonicalType(ClassType));    SourceLocation ClassLoc = ClassDecl->getLocation();    DeclarationNameInfo NameInfo(Name, ClassLoc); + +  //   An implicitly-declared copy constructor is an inline public +  //   member of its class.     CXXConstructorDecl *CopyConstructor      = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,                                   Context.getFunctionType(Context.VoidTy, @@ -6106,6 +7315,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(                                   /*isInline=*/true,                                   /*isImplicitlyDeclared=*/true);    CopyConstructor->setAccess(AS_public); +  CopyConstructor->setDefaulted();    CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());    // Note that we have declared this constructor. @@ -6119,19 +7329,22 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(                                                 SC_None,                                                 SC_None, 0);    CopyConstructor->setParams(&FromParam, 1); +    if (Scope *S = getScopeForContext(ClassDecl))      PushOnScopeChains(CopyConstructor, S, false);    ClassDecl->addDecl(CopyConstructor); + +  if (ShouldDeleteCopyConstructor(CopyConstructor)) +    CopyConstructor->setDeletedAsWritten();    return CopyConstructor;  }  void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, -                                   CXXConstructorDecl *CopyConstructor, -                                   unsigned TypeQuals) { -  assert((CopyConstructor->isImplicit() && -          CopyConstructor->isCopyConstructor(TypeQuals) && -          !CopyConstructor->isUsed(false)) && +                                   CXXConstructorDecl *CopyConstructor) { +  assert((CopyConstructor->isDefaulted() && +          CopyConstructor->isCopyConstructor() && +          !CopyConstructor->doesThisDeclarationHaveABody()) &&           "DefineImplicitCopyConstructor - call it for implicit copy ctor");    CXXRecordDecl *ClassDecl = CopyConstructor->getParent(); @@ -7138,7 +8351,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,    bool Invalid = false;    if (TemplateParameterList *TemplateParams -        = MatchTemplateParametersToScopeSpecifier(TagLoc, SS, +        = MatchTemplateParametersToScopeSpecifier(TagLoc, NameLoc, SS,                                                    TempParamLists.get(),                                                    TempParamLists.size(),                                                    /*friend*/ true, @@ -7554,7 +8767,83 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {      // If the declaration wasn't the first, we delete the function anyway for      // recovery.    } -  Fn->setDeleted(); +  Fn->setDeletedAsWritten(); +} + +void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { +  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Dcl); + +  if (MD) { +    if (MD->getParent()->isDependentType()) { +      MD->setDefaulted(); +      MD->setExplicitlyDefaulted(); +      return; +    } + +    CXXSpecialMember Member = getSpecialMember(MD); +    if (Member == CXXInvalid) { +      Diag(DefaultLoc, diag::err_default_special_members); +      return; +    } + +    MD->setDefaulted(); +    MD->setExplicitlyDefaulted(); + +    // If this definition appears within the record, do the checking when +    // the record is complete. +    const FunctionDecl *Primary = MD; +    if (MD->getTemplatedKind() != FunctionDecl::TK_NonTemplate) +      // Find the uninstantiated declaration that actually had the '= default' +      // on it. +      MD->getTemplateInstantiationPattern()->isDefined(Primary); + +    if (Primary == Primary->getCanonicalDecl()) +      return; + +    switch (Member) { +    case CXXDefaultConstructor: { +      CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD); +      CheckExplicitlyDefaultedDefaultConstructor(CD); +      if (!CD->isInvalidDecl()) +        DefineImplicitDefaultConstructor(DefaultLoc, CD); +      break; +    } + +    case CXXCopyConstructor: { +      CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD); +      CheckExplicitlyDefaultedCopyConstructor(CD); +      if (!CD->isInvalidDecl()) +        DefineImplicitCopyConstructor(DefaultLoc, CD); +      break; +    } + +    case CXXCopyAssignment: { +      CheckExplicitlyDefaultedCopyAssignment(MD); +      if (!MD->isInvalidDecl()) +        DefineImplicitCopyAssignment(DefaultLoc, MD); +      break; +    } + +    case CXXDestructor: { +      CXXDestructorDecl *DD = cast<CXXDestructorDecl>(MD); +      CheckExplicitlyDefaultedDestructor(DD); +      if (!DD->isInvalidDecl()) +        DefineImplicitDestructor(DefaultLoc, DD); +      break; +    } + +    case CXXMoveConstructor: +    case CXXMoveAssignment: +      Diag(Dcl->getLocation(), diag::err_defaulted_move_unsupported); +      break; + +    default: +      // FIXME: Do the rest once we have move functions +      break; +    } +  } else { +    Diag(DefaultLoc, diag::err_default_special_members); +  }  }  static void SearchForReturnInStmt(Sema &Self, Stmt *S) { @@ -7946,3 +9235,86 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {                                              AllToInit.data(), AllToInit.size());    }  } + +static +void DelegatingCycleHelper(CXXConstructorDecl* Ctor, +                           llvm::SmallSet<CXXConstructorDecl*, 4> &Valid, +                           llvm::SmallSet<CXXConstructorDecl*, 4> &Invalid, +                           llvm::SmallSet<CXXConstructorDecl*, 4> &Current, +                           Sema &S) { +  llvm::SmallSet<CXXConstructorDecl*, 4>::iterator CI = Current.begin(), +                                                   CE = Current.end(); +  if (Ctor->isInvalidDecl()) +    return; + +  const FunctionDecl *FNTarget = 0; +  CXXConstructorDecl *Target; +   +  // We ignore the result here since if we don't have a body, Target will be +  // null below. +  (void)Ctor->getTargetConstructor()->hasBody(FNTarget); +  Target += const_cast<CXXConstructorDecl*>(cast_or_null<CXXConstructorDecl>(FNTarget)); + +  CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(), +                     // Avoid dereferencing a null pointer here. +                     *TCanonical = Target ? Target->getCanonicalDecl() : 0; + +  if (!Current.insert(Canonical)) +    return; + +  // We know that beyond here, we aren't chaining into a cycle. +  if (!Target || !Target->isDelegatingConstructor() || +      Target->isInvalidDecl() || Valid.count(TCanonical)) { +    for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI) +      Valid.insert(*CI); +    Current.clear(); +  // We've hit a cycle. +  } else if (TCanonical == Canonical || Invalid.count(TCanonical) || +             Current.count(TCanonical)) { +    // If we haven't diagnosed this cycle yet, do so now. +    if (!Invalid.count(TCanonical)) { +      S.Diag((*Ctor->init_begin())->getSourceLocation(), +             diag::warn_delegating_ctor_cycle) +        << Ctor; + +      // Don't add a note for a function delegating directo to itself. +      if (TCanonical != Canonical) +        S.Diag(Target->getLocation(), diag::note_it_delegates_to); + +      CXXConstructorDecl *C = Target; +      while (C->getCanonicalDecl() != Canonical) { +        (void)C->getTargetConstructor()->hasBody(FNTarget); +        assert(FNTarget && "Ctor cycle through bodiless function"); + +        C +       = const_cast<CXXConstructorDecl*>(cast<CXXConstructorDecl>(FNTarget)); +        S.Diag(C->getLocation(), diag::note_which_delegates_to); +      } +    } + +    for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI) +      Invalid.insert(*CI); +    Current.clear(); +  } else { +    DelegatingCycleHelper(Target, Valid, Invalid, Current, S); +  } +} +    + +void Sema::CheckDelegatingCtorCycles() { +  llvm::SmallSet<CXXConstructorDecl*, 4> Valid, Invalid, Current; + +  llvm::SmallSet<CXXConstructorDecl*, 4>::iterator CI = Current.begin(), +                                                   CE = Current.end(); + +  for (llvm::SmallVector<CXXConstructorDecl*, 4>::iterator +         I = DelegatingCtorDecls.begin(), +         E = DelegatingCtorDecls.end(); +       I != E; ++I) { +   DelegatingCycleHelper(*I, Valid, Invalid, Current, *this); +  } + +  for (CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI) +    (*CI)->setInvalidDecl(); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp index 7b235bab5d9a..de9097e98b4f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp @@ -24,6 +24,141 @@  using namespace clang; +bool Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,  +                                   const ObjCMethodDecl *Overridden, +                                   bool IsImplementation) { +  if (Overridden->hasRelatedResultType() &&  +      !NewMethod->hasRelatedResultType()) { +    // This can only happen when the method follows a naming convention that +    // implies a related result type, and the original (overridden) method has +    // a suitable return type, but the new (overriding) method does not have +    // a suitable return type. +    QualType ResultType = NewMethod->getResultType(); +    SourceRange ResultTypeRange; +    if (const TypeSourceInfo *ResultTypeInfo  +        = NewMethod->getResultTypeSourceInfo()) +      ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange(); +     +    // Figure out which class this method is part of, if any. +    ObjCInterfaceDecl *CurrentClass  +      = dyn_cast<ObjCInterfaceDecl>(NewMethod->getDeclContext()); +    if (!CurrentClass) { +      DeclContext *DC = NewMethod->getDeclContext(); +      if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(DC)) +        CurrentClass = Cat->getClassInterface(); +      else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(DC)) +        CurrentClass = Impl->getClassInterface(); +      else if (ObjCCategoryImplDecl *CatImpl +               = dyn_cast<ObjCCategoryImplDecl>(DC)) +        CurrentClass = CatImpl->getClassInterface(); +    } +     +    if (CurrentClass) { +      Diag(NewMethod->getLocation(),  +           diag::warn_related_result_type_compatibility_class) +        << Context.getObjCInterfaceType(CurrentClass) +        << ResultType +        << ResultTypeRange; +    } else { +      Diag(NewMethod->getLocation(),  +           diag::warn_related_result_type_compatibility_protocol) +        << ResultType +        << ResultTypeRange; +    } +     +    Diag(Overridden->getLocation(), diag::note_related_result_type_overridden) +      << Overridden->getMethodFamily(); +  } +   +  return false; +} + + +static bool CheckObjCMethodOverrides(Sema &S, ObjCMethodDecl *NewMethod, +                                     DeclContext *DC,  +                                     bool SkipCurrent = true) { +  if (!DC) +    return false; +   +  if (!SkipCurrent) { +    // Look for this method. If we find it, we're done. +    Selector Sel = NewMethod->getSelector(); +    bool IsInstance = NewMethod->isInstanceMethod(); +    DeclContext::lookup_const_iterator Meth, MethEnd; +    for (llvm::tie(Meth, MethEnd) = DC->lookup(Sel); Meth != MethEnd; ++Meth) { +      ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth); +      if (MD && MD->isInstanceMethod() == IsInstance) +        return S.CheckObjCMethodOverride(NewMethod, MD, false); +    } +  } +   +  if (ObjCInterfaceDecl *Class = llvm::dyn_cast<ObjCInterfaceDecl>(DC)) { +    // Look through categories. +    for (ObjCCategoryDecl *Category = Class->getCategoryList(); +         Category; Category = Category->getNextClassCategory()) { +      if (CheckObjCMethodOverrides(S, NewMethod, Category, false)) +        return true; +    } +     +    // Look through protocols. +    for (ObjCList<ObjCProtocolDecl>::iterator I = Class->protocol_begin(), +         IEnd = Class->protocol_end(); +         I != IEnd; ++I) +      if (CheckObjCMethodOverrides(S, NewMethod, *I, false)) +        return true; +     +    // Look in our superclass. +    return CheckObjCMethodOverrides(S, NewMethod, Class->getSuperClass(),  +                                    false); +  } +   +  if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(DC)) { +    // Look through protocols. +    for (ObjCList<ObjCProtocolDecl>::iterator I = Category->protocol_begin(), +         IEnd = Category->protocol_end(); +         I != IEnd; ++I) +      if (CheckObjCMethodOverrides(S, NewMethod, *I, false)) +        return true; +     +    return false; +  } +   +  if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(DC)) { +    // Look through protocols. +    for (ObjCList<ObjCProtocolDecl>::iterator I = Protocol->protocol_begin(), +         IEnd = Protocol->protocol_end(); +         I != IEnd; ++I) +      if (CheckObjCMethodOverrides(S, NewMethod, *I, false)) +        return true; +     +    return false; +  } +   +  return false; +} + +bool Sema::CheckObjCMethodOverrides(ObjCMethodDecl *NewMethod,  +                                    DeclContext *DC) { +  if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(DC)) +    return ::CheckObjCMethodOverrides(*this, NewMethod, Class); +   +  if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(DC)) +    return ::CheckObjCMethodOverrides(*this, NewMethod, Category); +   +  if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(DC)) +    return ::CheckObjCMethodOverrides(*this, NewMethod, Protocol); +   +  if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(DC)) +    return ::CheckObjCMethodOverrides(*this, NewMethod,  +                                      Impl->getClassInterface()); +   +  if (ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(DC)) +    return ::CheckObjCMethodOverrides(*this, NewMethod,  +                                      CatImpl->getClassInterface()); +   +  return ::CheckObjCMethodOverrides(*this, NewMethod, CurContext); +} +  static void DiagnoseObjCImplementedDeprecations(Sema &S,                                                  NamedDecl *ND,                                                  SourceLocation ImplLoc, @@ -272,23 +407,27 @@ Decl *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,    return AliasDecl;  } -void Sema::CheckForwardProtocolDeclarationForCircularDependency( +bool Sema::CheckForwardProtocolDeclarationForCircularDependency(    IdentifierInfo *PName,    SourceLocation &Ploc, SourceLocation PrevLoc,    const ObjCList<ObjCProtocolDecl> &PList) { +   +  bool res = false;    for (ObjCList<ObjCProtocolDecl>::iterator I = PList.begin(),         E = PList.end(); I != E; ++I) { -      if (ObjCProtocolDecl *PDecl = LookupProtocol((*I)->getIdentifier(),                                                   Ploc)) {        if (PDecl->getIdentifier() == PName) {          Diag(Ploc, diag::err_protocol_has_circular_dependency);          Diag(PrevLoc, diag::note_previous_definition); +        res = true;        } -      CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc, -        PDecl->getLocation(), PDecl->getReferencedProtocols()); +      if (CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc, +            PDecl->getLocation(), PDecl->getReferencedProtocols())) +        res = true;      }    } +  return res;  }  Decl * @@ -300,6 +439,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,                                    const SourceLocation *ProtoLocs,                                    SourceLocation EndProtoLoc,                                    AttributeList *AttrList) { +  bool err = false;    // FIXME: Deal with AttrList.    assert(ProtocolName && "Missing protocol identifier");    ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolName, ProtocolLoc); @@ -314,8 +454,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,      }      ObjCList<ObjCProtocolDecl> PList;      PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context); -    CheckForwardProtocolDeclarationForCircularDependency( -      ProtocolName, ProtocolLoc, PDecl->getLocation(), PList); +    err = CheckForwardProtocolDeclarationForCircularDependency( +            ProtocolName, ProtocolLoc, PDecl->getLocation(), PList);      // Make sure the cached decl gets a valid start location.      PDecl->setLocation(AtProtoInterfaceLoc); @@ -331,7 +471,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,    }    if (AttrList)      ProcessDeclAttributeList(TUScope, PDecl, AttrList); -  if (NumProtoRefs) { +  if (!err && NumProtoRefs ) {      /// Check then save referenced protocols.      PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,                             ProtoLocs, Context); @@ -1712,11 +1852,71 @@ bool containsInvalidMethodImplAttribute(const AttrVec &A) {    return false;  } +/// \brief Check whether the declared result type of the given Objective-C +/// method declaration is compatible with the method's class. +/// +static bool  +CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method, +                                    ObjCInterfaceDecl *CurrentClass) { +  QualType ResultType = Method->getResultType(); +  SourceRange ResultTypeRange; +  if (const TypeSourceInfo *ResultTypeInfo = Method->getResultTypeSourceInfo()) +    ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange(); +   +  // If an Objective-C method inherits its related result type, then its  +  // declared result type must be compatible with its own class type. The +  // declared result type is compatible if: +  if (const ObjCObjectPointerType *ResultObjectType +                                = ResultType->getAs<ObjCObjectPointerType>()) { +    //   - it is id or qualified id, or +    if (ResultObjectType->isObjCIdType() || +        ResultObjectType->isObjCQualifiedIdType()) +      return false; +   +    if (CurrentClass) { +      if (ObjCInterfaceDecl *ResultClass  +                                      = ResultObjectType->getInterfaceDecl()) { +        //   - it is the same as the method's class type, or +        if (CurrentClass == ResultClass) +          return false; +         +        //   - it is a superclass of the method's class type +        if (ResultClass->isSuperClassOf(CurrentClass)) +          return false; +      }       +    } +  } +   +  return true; +} + +/// \brief Determine if any method in the global method pool has an inferred  +/// result type. +static bool  +anyMethodInfersRelatedResultType(Sema &S, Selector Sel, bool IsInstance) { +  Sema::GlobalMethodPool::iterator Pos = S.MethodPool.find(Sel); +  if (Pos == S.MethodPool.end()) { +    if (S.ExternalSource) +      Pos = S.ReadMethodPool(Sel); +    else +      return 0; +  } +   +  ObjCMethodList &List = IsInstance ? Pos->second.first : Pos->second.second; +  for (ObjCMethodList *M = &List; M; M = M->Next) { +    if (M->Method && M->Method->hasRelatedResultType()) +      return true; +  }   +   +  return false; +} +  Decl *Sema::ActOnMethodDeclaration(      Scope *S,      SourceLocation MethodLoc, SourceLocation EndLoc,      tok::TokenKind MethodType, Decl *ClassDecl,      ObjCDeclSpec &ReturnQT, ParsedType ReturnType, +    SourceLocation SelectorStartLoc,      Selector Sel,      // optional arguments. The number of types/arguments is obtained      // from the Sel.getNumArgs(). @@ -1741,7 +1941,7 @@ Decl *Sema::ActOnMethodDeclaration(        Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value)          << 0 << resultDeclType;        return 0; -    } +    }        } else // get the type for "id".      resultDeclType = Context.getObjCIdType(); @@ -1751,9 +1951,10 @@ Decl *Sema::ActOnMethodDeclaration(                             cast<DeclContext>(ClassDecl),                             MethodType == tok::minus, isVariadic,                             false, false, -                           MethodDeclKind == tok::objc_optional ? -                           ObjCMethodDecl::Optional : -                           ObjCMethodDecl::Required); +                           MethodDeclKind == tok::objc_optional  +                             ? ObjCMethodDecl::Optional +                             : ObjCMethodDecl::Required, +                           false);    llvm::SmallVector<ParmVarDecl*, 16> Params; @@ -1849,6 +2050,7 @@ Decl *Sema::ActOnMethodDeclaration(      }      InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel,                                                     MethodType == tok::minus); +          if (ObjCMethod->hasAttrs() &&          containsInvalidMethodImplAttribute(ObjCMethod->getAttrs()))        Diag(EndLoc, diag::warn_attribute_method_def); @@ -1861,6 +2063,10 @@ Decl *Sema::ActOnMethodDeclaration(        PrevMethod = CatImpDecl->getClassMethod(Sel);        CatImpDecl->addClassMethod(ObjCMethod);      } + +    if (ObjCCategoryDecl *Cat = CatImpDecl->getCategoryDecl()) +      InterfaceMD = Cat->getMethod(Sel, MethodType == tok::minus); +      if (ObjCMethod->hasAttrs() &&          containsInvalidMethodImplAttribute(ObjCMethod->getAttrs()))        Diag(EndLoc, diag::warn_attribute_method_def); @@ -1874,10 +2080,65 @@ Decl *Sema::ActOnMethodDeclaration(      Diag(PrevMethod->getLocation(), diag::note_previous_declaration);    } +  // If this Objective-C method does not have a related result type, but we +  // are allowed to infer related result types, try to do so based on the +  // method family. +  ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(ClassDecl); +  if (!CurrentClass) { +    if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) +      CurrentClass = Cat->getClassInterface(); +    else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(ClassDecl)) +      CurrentClass = Impl->getClassInterface(); +    else if (ObjCCategoryImplDecl *CatImpl +                                   = dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) +      CurrentClass = CatImpl->getClassInterface(); +  } +      // Merge information down from the interface declaration if we have one. -  if (InterfaceMD) +  if (InterfaceMD) { +    // Inherit the related result type, if we can. +    if (InterfaceMD->hasRelatedResultType() && +        !CheckRelatedResultTypeCompatibility(*this, ObjCMethod, CurrentClass)) +      ObjCMethod->SetRelatedResultType(); +            mergeObjCMethodDecls(ObjCMethod, InterfaceMD); - +  } +   +  if (!ObjCMethod->hasRelatedResultType() &&  +      getLangOptions().ObjCInferRelatedResultType) { +    bool InferRelatedResultType = false; +    switch (ObjCMethod->getMethodFamily()) { +    case OMF_None: +    case OMF_copy: +    case OMF_dealloc: +    case OMF_mutableCopy: +    case OMF_release: +    case OMF_retainCount: +      break; +       +    case OMF_alloc: +    case OMF_new: +      InferRelatedResultType = ObjCMethod->isClassMethod(); +      break; +         +    case OMF_init: +    case OMF_autorelease: +    case OMF_retain: +    case OMF_self: +      InferRelatedResultType = ObjCMethod->isInstanceMethod(); +      break; +    } +     +    if (InferRelatedResultType && +        !CheckRelatedResultTypeCompatibility(*this, ObjCMethod, CurrentClass)) +      ObjCMethod->SetRelatedResultType(); +     +    if (!InterfaceMD &&  +        anyMethodInfersRelatedResultType(*this, ObjCMethod->getSelector(), +                                         ObjCMethod->isInstanceMethod())) +      CheckObjCMethodOverrides(ObjCMethod, cast<DeclContext>(ClassDecl)); +  } +        return ObjCMethod;  } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp index f1033dc8c2ff..7bcec315ddab 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp @@ -298,8 +298,6 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,    //   - both are non-throwing, regardless of their form,    //   - both have the form noexcept(constant-expression) and the constant-    //     expressions are equivalent, -  //   - one exception-specification is a noexcept-specification allowing all -  //     exceptions and the other is of the form throw(type-id-list), or    //   - both are dynamic-exception-specifications that have the same set of    //     adjusted types.    // @@ -307,8 +305,6 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,    //   of the form throw(), noexcept, or noexcept(constant-expression) where the    //   constant-expression yields true.    // -  // CWG 1073 Proposed resolution: Strike the third bullet above. -  //    // C++0x [except.spec]p4: If any declaration of a function has an exception-    //   specifier that is not a noexcept-specification allowing all exceptions,    //   all declarations [...] of that function shall have a compatible @@ -320,6 +316,9 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,    ExceptionSpecificationType OldEST = Old->getExceptionSpecType();    ExceptionSpecificationType NewEST = New->getExceptionSpecType(); +  assert(OldEST != EST_Delayed && NewEST != EST_Delayed && +         "Shouldn't see unknown exception specifications here"); +    // Shortcut the case where both have no spec.    if (OldEST == EST_None && NewEST == EST_None)      return false; @@ -506,6 +505,9 @@ bool Sema::CheckExceptionSpecSubset(    ExceptionSpecificationType SubEST = Subset->getExceptionSpecType(); +  assert(SuperEST != EST_Delayed && SubEST != EST_Delayed && +         "Shouldn't see unknown exception specifications here"); +    // It does not. If the subset contains everything, we've failed.    if (SubEST == EST_None || SubEST == EST_MSAny) {      Diag(SubLoc, DiagID); @@ -701,7 +703,23 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)  bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,                                                  const CXXMethodDecl *Old) { -  return CheckExceptionSpecSubset(PDiag(diag::err_override_exception_spec), +  if (getLangOptions().CPlusPlus0x && isa<CXXDestructorDecl>(New)) { +    // Don't check uninstantiated template destructors at all. We can only +    // synthesize correct specs after the template is instantiated. +    if (New->getParent()->isDependentType()) +      return false; +    if (New->getParent()->isBeingDefined()) { +      // The destructor might be updated once the definition is finished. So +      // remember it and check later. +      DelayedDestructorExceptionSpecChecks.push_back(std::make_pair( +        cast<CXXDestructorDecl>(New), cast<CXXDestructorDecl>(Old))); +      return false; +    } +  } +  unsigned DiagID = diag::err_override_exception_spec; +  if (getLangOptions().Microsoft) +    DiagID = diag::warn_override_exception_spec; +  return CheckExceptionSpecSubset(PDiag(DiagID),                                    PDiag(diag::note_overridden_virtual_function),                                    Old->getType()->getAs<FunctionProtoType>(),                                    Old->getLocation(), diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp index 20b92b84203f..0549e9499560 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -449,18 +449,58 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,    if (FDecl && FDecl->getBuiltinID() == Builtin::BI__builtin_va_start)      return Owned(E); +  // Don't allow one to pass an Objective-C interface to a vararg.    if (E->getType()->isObjCObjectType() && -      DiagRuntimeBehavior(E->getLocStart(), 0, -        PDiag(diag::err_cannot_pass_objc_interface_to_vararg) -          << E->getType() << CT)) +    DiagRuntimeBehavior(E->getLocStart(), 0, +                        PDiag(diag::err_cannot_pass_objc_interface_to_vararg) +                          << E->getType() << CT))      return ExprError(); - -  if (!E->getType()->isPODType() && -      DiagRuntimeBehavior(E->getLocStart(), 0, +   +  if (!E->getType()->isPODType()) { +    // C++0x [expr.call]p7: +    //   Passing a potentially-evaluated argument of class type (Clause 9)  +    //   having a non-trivial copy constructor, a non-trivial move constructor, +    //   or a non-trivial destructor, with no corresponding parameter,  +    //   is conditionally-supported with implementation-defined semantics. +    bool TrivialEnough = false; +    if (getLangOptions().CPlusPlus0x && !E->getType()->isDependentType())  { +      if (CXXRecordDecl *Record = E->getType()->getAsCXXRecordDecl()) { +        if (Record->hasTrivialCopyConstructor() && +            Record->hasTrivialMoveConstructor() && +            Record->hasTrivialDestructor()) +          TrivialEnough = true; +      } +    } +       +    if (TrivialEnough) { +      // Nothing to diagnose. This is okay. +    } else if (DiagRuntimeBehavior(E->getLocStart(), 0,                            PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) -                            << E->getType() << CT)) -    return ExprError(); +                            << getLangOptions().CPlusPlus0x << E->getType()  +                            << CT)) { +      // Turn this into a trap. +      CXXScopeSpec SS; +      UnqualifiedId Name; +      Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"), +                         E->getLocStart()); +      ExprResult TrapFn = ActOnIdExpression(TUScope, SS, Name, true, false); +      if (TrapFn.isInvalid()) +        return ExprError(); +      ExprResult Call = ActOnCallExpr(TUScope, TrapFn.get(), E->getLocStart(), +                                      MultiExprArg(), E->getLocEnd()); +      if (Call.isInvalid()) +        return ExprError(); +       +      ExprResult Comma = ActOnBinOp(TUScope, E->getLocStart(), tok::comma, +                                    Call.get(), E); +      if (Comma.isInvalid()) +        return ExprError(); +       +      E = Comma.get(); +    } +  } +      return Owned(E);  } @@ -1293,8 +1333,8 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,      // We've found a member of an anonymous struct/union that is      // inside a non-anonymous struct/union, so in a well-formed      // program our base object expression is "this". -    CXXMethodDecl *method = tryCaptureCXXThis(); -    if (!method) { +    QualType ThisTy = getAndCaptureCurrentThisType(); +    if (ThisTy.isNull()) {        Diag(loc, diag::err_invalid_member_use_in_static_method)          << indirectField->getDeclName();        return ExprError(); @@ -1302,10 +1342,9 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,      // Our base object expression is "this".      baseObjectExpr = -      new (Context) CXXThisExpr(loc, method->getThisType(Context), -                                /*isImplicit=*/ true); +      new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/ true);      baseObjectIsPointer = true; -    baseQuals = Qualifiers::fromCVRMask(method->getTypeQualifiers()); +    baseQuals = ThisTy->castAs<PointerType>()->getPointeeType().getQualifiers();    }    // Build the implicit member references to the field of the @@ -1452,14 +1491,23 @@ enum IMAKind {  /// conservatively answer "yes", in which case some errors will simply  /// not be caught until template-instantiation.  static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, +                                            Scope *CurScope,                                              const LookupResult &R) {    assert(!R.empty() && (*R.begin())->isCXXClassMember());    DeclContext *DC = SemaRef.getFunctionLevelDeclContext(); +    bool isStaticContext =      (!isa<CXXMethodDecl>(DC) ||       cast<CXXMethodDecl>(DC)->isStatic()); +  // C++0x [expr.prim]p4: +  //   Otherwise, if a member-declarator declares a non-static data member +  // of a class X, the expression this is a prvalue of type "pointer to X" +  // within the optional brace-or-equal-initializer. +  if (CurScope->getFlags() & Scope::ThisScope) +    isStaticContext = false; +    if (R.isUnresolvableResult())      return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved; @@ -1507,8 +1555,11 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,      return IMA_Error_StaticContext;    } -  CXXRecordDecl * -        contextClass = cast<CXXMethodDecl>(DC)->getParent()->getCanonicalDecl(); +  CXXRecordDecl *contextClass; +  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) +    contextClass = MD->getParent()->getCanonicalDecl(); +  else +    contextClass = cast<CXXRecordDecl>(DC);    // [class.mfct.non-static]p3:     // ...is used in the body of a non-static member function of class X, @@ -1986,7 +2037,7 @@ ExprResult  Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,                                        LookupResult &R,                                  const TemplateArgumentListInfo *TemplateArgs) { -  switch (ClassifyImplicitMemberAccess(*this, R)) { +  switch (ClassifyImplicitMemberAccess(*this, CurScope, R)) {    case IMA_Instance:      return BuildImplicitMemberExpr(SS, R, TemplateArgs, true); @@ -2429,19 +2480,18 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,    // If this is known to be an instance access, go ahead and build an    // implicit 'this' expression now.    // 'this' expression now. -  CXXMethodDecl *method = tryCaptureCXXThis(); -  assert(method && "didn't correctly pre-flight capture of 'this'"); +  QualType ThisTy = getAndCaptureCurrentThisType(); +  assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'"); -  QualType thisType = method->getThisType(Context);    Expr *baseExpr = 0; // null signifies implicit access    if (IsKnownInstance) {      SourceLocation Loc = R.getNameLoc();      if (SS.getRange().isValid())        Loc = SS.getRange().getBegin(); -    baseExpr = new (Context) CXXThisExpr(loc, thisType, /*isImplicit=*/true); +    baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true);    } -  return BuildMemberReferenceExpr(baseExpr, thisType, +  return BuildMemberReferenceExpr(baseExpr, ThisTy,                                    /*OpLoc*/ SourceLocation(),                                    /*IsArrow*/ true,                                    SS, @@ -3014,8 +3064,120 @@ ExprResult Sema::ActOnParenExpr(SourceLocation L,    return Owned(new (Context) ParenExpr(L, R, E));  } +static bool CheckVecStepTraitOperandType(Sema &S, QualType T, +                                         SourceLocation Loc, +                                         SourceRange ArgRange) { +  // [OpenCL 1.1 6.11.12] "The vec_step built-in function takes a built-in +  // scalar or vector data type argument..." +  // Every built-in scalar type (OpenCL 1.1 6.1.1) is either an arithmetic +  // type (C99 6.2.5p18) or void. +  if (!(T->isArithmeticType() || T->isVoidType() || T->isVectorType())) { +    S.Diag(Loc, diag::err_vecstep_non_scalar_vector_type) +      << T << ArgRange; +    return true; +  } + +  assert((T->isVoidType() || !T->isIncompleteType()) && +         "Scalar types should always be complete"); +  return false; +} + +static bool CheckExtensionTraitOperandType(Sema &S, QualType T, +                                           SourceLocation Loc, +                                           SourceRange ArgRange, +                                           UnaryExprOrTypeTrait TraitKind) { +  // C99 6.5.3.4p1: +  if (T->isFunctionType()) { +    // alignof(function) is allowed as an extension. +    if (TraitKind == UETT_SizeOf) +      S.Diag(Loc, diag::ext_sizeof_function_type) << ArgRange; +    return false; +  } + +  // Allow sizeof(void)/alignof(void) as an extension. +  if (T->isVoidType()) { +    S.Diag(Loc, diag::ext_sizeof_void_type) << TraitKind << ArgRange; +    return false; +  } + +  return true; +} + +static bool CheckObjCTraitOperandConstraints(Sema &S, QualType T, +                                             SourceLocation Loc, +                                             SourceRange ArgRange, +                                             UnaryExprOrTypeTrait TraitKind) { +  // Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode. +  if (S.LangOpts.ObjCNonFragileABI && T->isObjCObjectType()) { +    S.Diag(Loc, diag::err_sizeof_nonfragile_interface) +      << T << (TraitKind == UETT_SizeOf) +      << ArgRange; +    return true; +  } + +  return false; +} + +/// \brief Check the constrains on expression operands to unary type expression +/// and type traits. +/// +/// Completes any types necessary and validates the constraints on the operand +/// expression. The logic mostly mirrors the type-based overload, but may modify +/// the expression as it completes the type for that expression through template +/// instantiation, etc. +bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *Op, +                                            UnaryExprOrTypeTrait ExprKind) { +  QualType ExprTy = Op->getType(); + +  // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, +  //   the result is the size of the referenced type." +  // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the +  //   result shall be the alignment of the referenced type." +  if (const ReferenceType *Ref = ExprTy->getAs<ReferenceType>()) +    ExprTy = Ref->getPointeeType(); + +  if (ExprKind == UETT_VecStep) +    return CheckVecStepTraitOperandType(*this, ExprTy, Op->getExprLoc(), +                                        Op->getSourceRange()); + +  // Whitelist some types as extensions +  if (!CheckExtensionTraitOperandType(*this, ExprTy, Op->getExprLoc(), +                                      Op->getSourceRange(), ExprKind)) +    return false; + +  if (RequireCompleteExprType(Op, +                              PDiag(diag::err_sizeof_alignof_incomplete_type) +                              << ExprKind << Op->getSourceRange(), +                              std::make_pair(SourceLocation(), PDiag(0)))) +    return true; + +  // Completeing the expression's type may have changed it. +  ExprTy = Op->getType(); +  if (const ReferenceType *Ref = ExprTy->getAs<ReferenceType>()) +    ExprTy = Ref->getPointeeType(); + +  if (CheckObjCTraitOperandConstraints(*this, ExprTy, Op->getExprLoc(), +                                       Op->getSourceRange(), ExprKind)) +    return true; + +  return false; +} + +/// \brief Check the constraints on operands to unary expression and type +/// traits. +/// +/// This will complete any types necessary, and validate the various constraints +/// on those operands. +///  /// The UsualUnaryConversions() function is *not* called by this routine. -/// See C99 6.3.2.1p[2-4] for more details. +/// C99 6.3.2.1p[2-4] all state: +///   Except when it is the operand of the sizeof operator ... +/// +/// C++ [expr.sizeof]p4 +///   The lvalue-to-rvalue, array-to-pointer, and function-to-pointer +///   standard conversions are not applied to the operand of sizeof. +/// +/// This policy is followed for all of the unary trait expressions.  bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType exprType,                                              SourceLocation OpLoc,                                              SourceRange ExprRange, @@ -3030,55 +3192,27 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType exprType,    if (const ReferenceType *Ref = exprType->getAs<ReferenceType>())      exprType = Ref->getPointeeType(); -  // [OpenCL 1.1 6.11.12] "The vec_step built-in function takes a built-in -  // scalar or vector data type argument..." -  // Every built-in scalar type (OpenCL 1.1 6.1.1) is either an arithmetic -  // type (C99 6.2.5p18) or void. -  if (ExprKind == UETT_VecStep) { -    if (!(exprType->isArithmeticType() || exprType->isVoidType() || -          exprType->isVectorType())) { -      Diag(OpLoc, diag::err_vecstep_non_scalar_vector_type) -        << exprType << ExprRange; -      return true; -    } -  } +  if (ExprKind == UETT_VecStep) +    return CheckVecStepTraitOperandType(*this, exprType, OpLoc, ExprRange); -  // C99 6.5.3.4p1: -  if (exprType->isFunctionType()) { -    // alignof(function) is allowed as an extension. -    if (ExprKind == UETT_SizeOf) -      Diag(OpLoc, diag::ext_sizeof_function_type)  -        << ExprRange; +  // Whitelist some types as extensions +  if (!CheckExtensionTraitOperandType(*this, exprType, OpLoc, ExprRange, +                                      ExprKind))      return false; -  } - -  // Allow sizeof(void)/alignof(void) as an extension.  vec_step(void) is not -  // an extension, as void is a built-in scalar type (OpenCL 1.1 6.1.1). -  if (exprType->isVoidType()) { -    if (ExprKind != UETT_VecStep) -      Diag(OpLoc, diag::ext_sizeof_void_type) -        << ExprKind << ExprRange; -    return false; -  }    if (RequireCompleteType(OpLoc, exprType,                            PDiag(diag::err_sizeof_alignof_incomplete_type)                            << ExprKind << ExprRange))      return true; -  // Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode. -  if (LangOpts.ObjCNonFragileABI && exprType->isObjCObjectType()) { -    Diag(OpLoc, diag::err_sizeof_nonfragile_interface) -      << exprType << (ExprKind == UETT_SizeOf) -      << ExprRange; +  if (CheckObjCTraitOperandConstraints(*this, exprType, OpLoc, ExprRange, +                                       ExprKind))      return true; -  }    return false;  } -static bool CheckAlignOfExpr(Sema &S, Expr *E, SourceLocation OpLoc, -                             SourceRange ExprRange) { +static bool CheckAlignOfExpr(Sema &S, Expr *E) {    E = E->IgnoreParens();    // alignof decl is always ok. @@ -3090,7 +3224,8 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E, SourceLocation OpLoc,      return false;    if (E->getBitField()) { -   S. Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 1 << ExprRange; +    S.Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) +       << 1 << E->getSourceRange();      return true;    } @@ -3100,20 +3235,17 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E, SourceLocation OpLoc,      if (isa<FieldDecl>(ME->getMemberDecl()))        return false; -  return S.CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, ExprRange, -                                            UETT_AlignOf); +  return S.CheckUnaryExprOrTypeTraitOperand(E, UETT_AlignOf);  } -bool Sema::CheckVecStepExpr(Expr *E, SourceLocation OpLoc, -                            SourceRange ExprRange) { +bool Sema::CheckVecStepExpr(Expr *E) {    E = E->IgnoreParens();    // Cannot know anything else if the expression is dependent.    if (E->isTypeDependent())      return false; -  return CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, ExprRange, -                                          UETT_VecStep); +  return CheckUnaryExprOrTypeTraitOperand(E, UETT_VecStep);  }  /// \brief Build a sizeof or alignof expression given a type operand. @@ -3141,35 +3273,33 @@ Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,  /// operand.  ExprResult  Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, -                                     UnaryExprOrTypeTrait ExprKind, -                                     SourceRange R) { +                                     UnaryExprOrTypeTrait ExprKind) {    // Verify that the operand is valid.    bool isInvalid = false;    if (E->isTypeDependent()) {      // Delay type-checking for type-dependent expressions.    } else if (ExprKind == UETT_AlignOf) { -    isInvalid = CheckAlignOfExpr(*this, E, OpLoc, R); +    isInvalid = CheckAlignOfExpr(*this, E);    } else if (ExprKind == UETT_VecStep) { -    isInvalid = CheckVecStepExpr(E, OpLoc, R); +    isInvalid = CheckVecStepExpr(E);    } else if (E->getBitField()) {  // C99 6.5.3.4p1. -    Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 0; +    Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) << 0;      isInvalid = true;    } else if (E->getType()->isPlaceholderType()) {      ExprResult PE = CheckPlaceholderExpr(E);      if (PE.isInvalid()) return ExprError(); -    return CreateUnaryExprOrTypeTraitExpr(PE.take(), OpLoc, ExprKind, R); +    return CreateUnaryExprOrTypeTraitExpr(PE.take(), OpLoc, ExprKind);    } else { -    isInvalid = CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, R, -                                                 UETT_SizeOf); +    isInvalid = CheckUnaryExprOrTypeTraitOperand(E, UETT_SizeOf);    }    if (isInvalid)      return ExprError();    // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t. -  return Owned(new (Context) UnaryExprOrTypeTraitExpr(ExprKind, E, -                                                      Context.getSizeType(), -                                                      OpLoc, R.getEnd())); +  return Owned(new (Context) UnaryExprOrTypeTraitExpr( +      ExprKind, E, Context.getSizeType(), OpLoc, +      E->getSourceRange().getEnd()));  }  /// ActOnUnaryExprOrTypeTraitExpr - Handle @c sizeof(type) and @c sizeof @c @@ -3189,10 +3319,7 @@ Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,    }    Expr *ArgEx = (Expr *)TyOrEx; -  ExprResult Result -    = CreateUnaryExprOrTypeTraitExpr(ArgEx, OpLoc, ExprKind, -                                     ArgEx->getSourceRange()); - +  ExprResult Result = CreateUnaryExprOrTypeTraitExpr(ArgEx, OpLoc, ExprKind);    return move(Result);  } @@ -4211,7 +4338,11 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,            if (DiagnoseUseOfDecl(PD, MemberLoc))              return ExprError(); -          return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), +          QualType T = PD->getType(); +          if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) +            T = getMessageSendResultType(BaseType, Getter, false, false); +          +          return Owned(new (Context) ObjCPropertyRefExpr(PD, T,                                                           VK_LValue,                                                           OK_ObjCProperty,                                                           MemberLoc,  @@ -4229,7 +4360,8 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,            if (Decl *SDecl = FindGetterSetterNameDecl(OPT, /*Property id*/0,                                                        SetterSel, Context))              SMD = dyn_cast<ObjCMethodDecl>(SDecl); -          QualType PType = OMD->getSendResultType(); +          QualType PType = getMessageSendResultType(BaseType, OMD, false,  +                                                    false);            ExprValueKind VK = VK_LValue;            if (!getLangOptions().CPlusPlus && @@ -4297,7 +4429,8 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,          ExprValueKind VK = VK_LValue;          if (Getter) { -          PType = Getter->getSendResultType(); +          PType = getMessageSendResultType(QualType(OT, 0), Getter, true,  +                                           false);            if (!getLangOptions().CPlusPlus &&                IsCForbiddenLValueType(Context, PType))              VK = VK_RValue; @@ -4377,120 +4510,52 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,    // If the user is trying to apply -> or . to a function name, it's probably    // because they forgot parentheses to call that function. -  bool TryCall = false; -  bool Overloaded = false; -  UnresolvedSet<8> AllOverloads; -  if (const OverloadExpr *Overloads = dyn_cast<OverloadExpr>(BaseExpr.get())) { -    AllOverloads.append(Overloads->decls_begin(), Overloads->decls_end()); -    TryCall = true; -    Overloaded = true; -  } else if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(BaseExpr.get())) { -    if (FunctionDecl* Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) { -      AllOverloads.addDecl(Fun); -      TryCall = true; -    } -  } - -  if (TryCall) { -    // Plunder the overload set for something that would make the member -    // expression valid. -    UnresolvedSet<4> ViableOverloads; -    bool HasViableZeroArgOverload = false; -    for (OverloadExpr::decls_iterator it = AllOverloads.begin(), -         DeclsEnd = AllOverloads.end(); it != DeclsEnd; ++it) { -      // Our overload set may include TemplateDecls, which we'll ignore for the -      // purposes of determining whether we can issue a '()' fixit. -      if (const FunctionDecl *OverloadDecl = dyn_cast<FunctionDecl>(*it)) { -        QualType ResultTy = OverloadDecl->getResultType(); -        if ((!IsArrow && ResultTy->isRecordType()) || -            (IsArrow && ResultTy->isPointerType() && -             ResultTy->getPointeeType()->isRecordType())) { -          ViableOverloads.addDecl(*it); -          if (OverloadDecl->getMinRequiredArguments() == 0) { -            HasViableZeroArgOverload = true; -          } -        } -      } -    } - -    if (!HasViableZeroArgOverload || ViableOverloads.size() != 1) { +  QualType ZeroArgCallTy; +  UnresolvedSet<4> Overloads; +  if (isExprCallable(*BaseExpr.get(), ZeroArgCallTy, Overloads)) { +    if (ZeroArgCallTy.isNull()) {        Diag(BaseExpr.get()->getExprLoc(), diag::err_member_reference_needs_call) -          << (AllOverloads.size() > 1) << 0 -          << BaseExpr.get()->getSourceRange(); -      int ViableOverloadCount = ViableOverloads.size(); -      int I; -      for (I = 0; I < ViableOverloadCount; ++I) { -        // FIXME: Magic number for max shown overloads stolen from -        // OverloadCandidateSet::NoteCandidates. -        if (I >= 4 && Diags.getShowOverloads() == Diagnostic::Ovl_Best) { -          break; -        } -        Diag(ViableOverloads[I].getDecl()->getSourceRange().getBegin(), -             diag::note_member_ref_possible_intended_overload); -      } -      if (I != ViableOverloadCount) { -        Diag(BaseExpr.get()->getExprLoc(), diag::note_ovl_too_many_candidates) -            << int(ViableOverloadCount - I); +          << (Overloads.size() > 1) << 0 << BaseExpr.get()->getSourceRange(); +      UnresolvedSet<2> PlausibleOverloads; +      for (OverloadExpr::decls_iterator It = Overloads.begin(), +           DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) { +        const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*It); +        QualType OverloadResultTy = OverloadDecl->getResultType(); +        if ((!IsArrow && OverloadResultTy->isRecordType()) || +            (IsArrow && OverloadResultTy->isPointerType() && +             OverloadResultTy->getPointeeType()->isRecordType())) +          PlausibleOverloads.addDecl(It.getDecl());        } +      NoteOverloads(PlausibleOverloads, BaseExpr.get()->getExprLoc());        return ExprError();      } -  } else { -    // We don't have an expression that's convenient to get a Decl from, but we -    // can at least check if the type is "function of 0 arguments which returns -    // an acceptable type". -    const FunctionType *Fun = NULL; -    if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { -      if ((Fun = Ptr->getPointeeType()->getAs<FunctionType>())) { -        TryCall = true; -      } -    } else if ((Fun = BaseType->getAs<FunctionType>())) { -      TryCall = true; -    } else if (BaseType == Context.BoundMemberTy) { -      // Look for the bound-member type.  If it's still overloaded, -      // give up, although we probably should have fallen into the -      // OverloadExpr case above if we actually have an overloaded -      // bound member. -      QualType fnType = Expr::findBoundMemberType(BaseExpr.get()); -      if (!fnType.isNull()) { -        TryCall = true; -        Fun = fnType->castAs<FunctionType>(); -      } -    } - -    if (TryCall) { -      if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Fun)) { -        if (FPT->getNumArgs() == 0) { -          QualType ResultTy = Fun->getResultType(); -          TryCall = (!IsArrow && ResultTy->isRecordType()) || -              (IsArrow && ResultTy->isPointerType() && -               ResultTy->getPointeeType()->isRecordType()); -        } -      } +    if ((!IsArrow && ZeroArgCallTy->isRecordType()) || +        (IsArrow && ZeroArgCallTy->isPointerType() && +         ZeroArgCallTy->getPointeeType()->isRecordType())) { +      // At this point, we know BaseExpr looks like it's potentially callable +      // with 0 arguments, and that it returns something of a reasonable type, +      // so we can emit a fixit and carry on pretending that BaseExpr was +      // actually a CallExpr. +      SourceLocation ParenInsertionLoc = +          PP.getLocForEndOfToken(BaseExpr.get()->getLocEnd()); +      Diag(BaseExpr.get()->getExprLoc(), diag::err_member_reference_needs_call) +          << (Overloads.size() > 1) << 1 << BaseExpr.get()->getSourceRange() +          << FixItHint::CreateInsertion(ParenInsertionLoc, "()"); +      // FIXME: Try this before emitting the fixit, and suppress diagnostics +      // while doing so. +      ExprResult NewBase = +          ActOnCallExpr(0, BaseExpr.take(), ParenInsertionLoc, +                        MultiExprArg(*this, 0, 0), +                        ParenInsertionLoc.getFileLocWithOffset(1)); +      if (NewBase.isInvalid()) +        return ExprError(); +      BaseExpr = NewBase; +      BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); +      return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, +                              ObjCImpDecl, HasTemplateArgs);      }    } -  if (TryCall) { -    // At this point, we know BaseExpr looks like it's potentially callable with -    // 0 arguments, and that it returns something of a reasonable type, so we -    // can emit a fixit and carry on pretending that BaseExpr was actually a -    // CallExpr. -    SourceLocation ParenInsertionLoc = -        PP.getLocForEndOfToken(BaseExpr.get()->getLocEnd()); -    Diag(BaseExpr.get()->getExprLoc(), diag::err_member_reference_needs_call) -        << int(Overloaded) << 1 -        << BaseExpr.get()->getSourceRange() -        << FixItHint::CreateInsertion(ParenInsertionLoc, "()"); -    ExprResult NewBase = ActOnCallExpr(0, BaseExpr.take(), ParenInsertionLoc, -                                       MultiExprArg(*this, 0, 0), -                                       ParenInsertionLoc); -    if (NewBase.isInvalid()) -      return ExprError(); -    BaseExpr = NewBase; -    BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); -    return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, -                            ObjCImpDecl, HasTemplateArgs); -  } -    Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union)      << BaseType << BaseExpr.get()->getSourceRange(); @@ -4946,6 +5011,26 @@ Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,    return ActOnCallExpr(S, ConfigDR, LLLLoc, execConfig, GGGLoc, 0);  } +/// ActOnAsTypeExpr - create a new asType (bitcast) from the arguments. +/// +/// __builtin_astype( value, dst type ) +/// +ExprResult Sema::ActOnAsTypeExpr(Expr *expr, ParsedType destty, +                                 SourceLocation BuiltinLoc, +                                 SourceLocation RParenLoc) { +  ExprValueKind VK = VK_RValue; +  ExprObjectKind OK = OK_Ordinary; +  QualType DstTy = GetTypeFromParser(destty); +  QualType SrcTy = expr->getType(); +  if (Context.getTypeSize(DstTy) != Context.getTypeSize(SrcTy)) +    return ExprError(Diag(BuiltinLoc, +                          diag::err_invalid_astype_of_different_size) +                     << DstTy +                     << SrcTy +                     << expr->getSourceRange()); +  return Owned(new (Context) AsTypeExpr(expr, DstTy, VK, OK, BuiltinLoc, RParenLoc)); +} +  /// 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 @@ -6118,6 +6203,150 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,    return QualType();  } +/// SuggestParentheses - Emit a diagnostic together with a fixit hint that wraps +/// ParenRange in parentheses. +static void SuggestParentheses(Sema &Self, SourceLocation Loc, +                               const PartialDiagnostic &PD, +                               const PartialDiagnostic &FirstNote, +                               SourceRange FirstParenRange, +                               const PartialDiagnostic &SecondNote, +                               SourceRange SecondParenRange) { +  Self.Diag(Loc, PD); + +  if (!FirstNote.getDiagID()) +    return; + +  SourceLocation EndLoc = Self.PP.getLocForEndOfToken(FirstParenRange.getEnd()); +  if (!FirstParenRange.getEnd().isFileID() || EndLoc.isInvalid()) { +    // We can't display the parentheses, so just return. +    return; +  } + +  Self.Diag(Loc, FirstNote) +    << FixItHint::CreateInsertion(FirstParenRange.getBegin(), "(") +    << FixItHint::CreateInsertion(EndLoc, ")"); + +  if (!SecondNote.getDiagID()) +    return; + +  EndLoc = Self.PP.getLocForEndOfToken(SecondParenRange.getEnd()); +  if (!SecondParenRange.getEnd().isFileID() || EndLoc.isInvalid()) { +    // We can't display the parentheses, so just dig the +    // warning/error and return. +    Self.Diag(Loc, SecondNote); +    return; +  } + +  Self.Diag(Loc, SecondNote) +    << FixItHint::CreateInsertion(SecondParenRange.getBegin(), "(") +    << FixItHint::CreateInsertion(EndLoc, ")"); +} + +static bool IsArithmeticOp(BinaryOperatorKind Opc) { +  return Opc >= BO_Mul && Opc <= BO_Shr; +} + +/// IsArithmeticBinaryExpr - Returns true if E is an arithmetic binary +/// expression, either using a built-in or overloaded operator, +/// and sets *OpCode to the opcode and *RHS to the right-hand side expression. +static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode, +                                   Expr **RHS) { +  E = E->IgnoreParenImpCasts(); +  E = E->IgnoreConversionOperator(); +  E = E->IgnoreParenImpCasts(); + +  // Built-in binary operator. +  if (BinaryOperator *OP = dyn_cast<BinaryOperator>(E)) { +    if (IsArithmeticOp(OP->getOpcode())) { +      *Opcode = OP->getOpcode(); +      *RHS = OP->getRHS(); +      return true; +    } +  } + +  // Overloaded operator. +  if (CXXOperatorCallExpr *Call = dyn_cast<CXXOperatorCallExpr>(E)) { +    if (Call->getNumArgs() != 2) +      return false; + +    // Make sure this is really a binary operator that is safe to pass into +    // BinaryOperator::getOverloadedOpcode(), e.g. it's not a subscript op. +    OverloadedOperatorKind OO = Call->getOperator(); +    if (OO < OO_Plus || OO > OO_Arrow) +      return false; + +    BinaryOperatorKind OpKind = BinaryOperator::getOverloadedOpcode(OO); +    if (IsArithmeticOp(OpKind)) { +      *Opcode = OpKind; +      *RHS = Call->getArg(1); +      return true; +    } +  } + +  return false; +} + +static bool IsLogicOp(BinaryOperatorKind Opc) { +  return (Opc >= BO_LT && Opc <= BO_NE) || (Opc >= BO_LAnd && Opc <= BO_LOr); +} + +/// ExprLooksBoolean - Returns true if E looks boolean, i.e. it has boolean type +/// or is a logical expression such as (x==y) which has int type, but is +/// commonly interpreted as boolean. +static bool ExprLooksBoolean(Expr *E) { +  E = E->IgnoreParenImpCasts(); + +  if (E->getType()->isBooleanType()) +    return true; +  if (BinaryOperator *OP = dyn_cast<BinaryOperator>(E)) +    return IsLogicOp(OP->getOpcode()); +  if (UnaryOperator *OP = dyn_cast<UnaryOperator>(E)) +    return OP->getOpcode() == UO_LNot; + +  return false; +} + +/// DiagnoseConditionalPrecedence - Emit a warning when a conditional operator +/// and binary operator are mixed in a way that suggests the programmer assumed +/// the conditional operator has higher precedence, for example: +/// "int x = a + someBinaryCondition ? 1 : 2". +static void DiagnoseConditionalPrecedence(Sema &Self, +                                          SourceLocation OpLoc, +                                          Expr *cond, +                                          Expr *lhs, +                                          Expr *rhs) { +  BinaryOperatorKind CondOpcode; +  Expr *CondRHS; + +  if (!IsArithmeticBinaryExpr(cond, &CondOpcode, &CondRHS)) +    return; +  if (!ExprLooksBoolean(CondRHS)) +    return; + +  // The condition is an arithmetic binary expression, with a right- +  // hand side that looks boolean, so warn. + +  PartialDiagnostic Warn = Self.PDiag(diag::warn_precedence_conditional) +      << cond->getSourceRange() +      << BinaryOperator::getOpcodeStr(CondOpcode); + +  PartialDiagnostic FirstNote = +      Self.PDiag(diag::note_precedence_conditional_silence) +      << BinaryOperator::getOpcodeStr(CondOpcode); + +  SourceRange FirstParenRange(cond->getLocStart(), +                              cond->getLocEnd()); + +  PartialDiagnostic SecondNote = +      Self.PDiag(diag::note_precedence_conditional_first); + +  SourceRange SecondParenRange(CondRHS->getLocStart(), +                               rhs->getLocEnd()); + +  SuggestParentheses(Self, OpLoc, Warn, FirstNote, FirstParenRange, +                     SecondNote, SecondParenRange); +} +  /// ActOnConditionalOp - Parse a ?: operation.  Note that 'LHS' may be null  /// in the case of a the GNU conditional expr extension.  ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, @@ -6162,6 +6391,9 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,        RHS.isInvalid())      return ExprError(); +  DiagnoseConditionalPrecedence(*this, QuestionLoc, Cond.get(), LHS.get(), +                                RHS.get()); +    if (!commonExpr)      return Owned(new (Context) ConditionalOperator(Cond.take(), QuestionLoc,                                                     LHS.take(), ColonLoc,  @@ -7487,7 +7719,7 @@ QualType Sema::CheckCompareOperands(ExprResult &lex, ExprResult &rex, SourceLoca      // Comparison of pointers with null pointer constants and equality      // comparisons of member pointers to null pointer constants.      if (RHSIsNull && -        ((lType->isPointerType() || lType->isNullPtrType()) || +        ((lType->isAnyPointerType() || lType->isNullPtrType()) ||           (!isRelational && lType->isMemberPointerType()))) {        rex = ImpCastExprToType(rex.take(), lType,                           lType->isMemberPointerType() @@ -7496,7 +7728,7 @@ QualType Sema::CheckCompareOperands(ExprResult &lex, ExprResult &rex, SourceLoca        return ResultTy;      }      if (LHSIsNull && -        ((rType->isPointerType() || rType->isNullPtrType()) || +        ((rType->isAnyPointerType() || rType->isNullPtrType()) ||           (!isRelational && rType->isMemberPointerType()))) {        lex = ImpCastExprToType(lex.take(), rType,                           rType->isMemberPointerType() @@ -7748,13 +7980,15 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]      // If the RHS can be constant folded, and if it constant folds to something      // that isn't 0 or 1 (which indicate a potential logical operation that      // happened to fold to true/false) then warn. +    // Parens on the RHS are ignored.      Expr::EvalResult Result; -    if (rex.get()->Evaluate(Result, Context) && !Result.HasSideEffects && -        Result.Val.getInt() != 0 && Result.Val.getInt() != 1) { -      Diag(Loc, diag::warn_logical_instead_of_bitwise) -       << rex.get()->getSourceRange() -        << (Opc == BO_LAnd ? "&&" : "||") -        << (Opc == BO_LAnd ? "&" : "|"); +    if (rex.get()->Evaluate(Result, Context) && !Result.HasSideEffects) +      if ((getLangOptions().Bool && !rex.get()->getType()->isBooleanType()) || +          (Result.Val.getInt() != 0 && Result.Val.getInt() != 1)) { +        Diag(Loc, diag::warn_logical_instead_of_bitwise) +          << rex.get()->getSourceRange() +          << (Opc == BO_LAnd ? "&&" : "||") +          << (Opc == BO_LAnd ? "&" : "|");      }    } @@ -8127,20 +8361,31 @@ ExprResult Sema::ConvertPropertyForRValue(Expr *E) {           E->getObjectKind() == OK_ObjCProperty);    const ObjCPropertyRefExpr *PRE = E->getObjCProperty(); +  QualType T = E->getType(); +  QualType ReceiverType; +  if (PRE->isObjectReceiver()) +    ReceiverType = PRE->getBase()->getType(); +  else if (PRE->isSuperReceiver()) +    ReceiverType = PRE->getSuperReceiverType(); +  else +    ReceiverType = Context.getObjCInterfaceType(PRE->getClassReceiver()); +        ExprValueKind VK = VK_RValue;    if (PRE->isImplicitProperty()) { -    if (const ObjCMethodDecl *GetterMethod =  +    if (ObjCMethodDecl *GetterMethod =             PRE->getImplicitPropertyGetter()) { -      QualType Result = GetterMethod->getResultType(); -      VK = Expr::getValueKindForType(Result); +      T = getMessageSendResultType(ReceiverType, GetterMethod,  +                                   PRE->isClassReceiver(),  +                                   PRE->isSuperReceiver()); +      VK = Expr::getValueKindForType(GetterMethod->getResultType());      }      else {        Diag(PRE->getLocation(), diag::err_getter_not_found)              << PRE->getBase()->getType();      }    } - -  E = ImplicitCastExpr::Create(Context, E->getType(), CK_GetObjCProperty, +   +  E = ImplicitCastExpr::Create(Context, T, CK_GetObjCProperty,                                 E, 0, VK);    ExprResult Result = MaybeBindToTemporary(E); @@ -8404,7 +8649,13 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,    Op = ConvResult.take();    QualType OpTy = Op->getType();    QualType Result; -   + +  if (isa<CXXReinterpretCastExpr>(Op)) { +    QualType OpOrigType = Op->IgnoreParenCasts()->getType(); +    S.CheckCompatibleReinterpretCast(OpOrigType, OpTy, /*IsDereference*/true, +                                     Op->getSourceRange()); +  } +    // Note that per both C89 and C99, indirection is always legal, even if OpTy    // is an incomplete type or void.  It would be possible to warn about    // dereferencing a void pointer, but it's completely well-defined, and such a @@ -8678,45 +8929,6 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,                                                      CompResultTy, OpLoc));  } -/// SuggestParentheses - Emit a diagnostic together with a fixit hint that wraps -/// ParenRange in parentheses. -static void SuggestParentheses(Sema &Self, SourceLocation Loc, -                               const PartialDiagnostic &PD, -                               const PartialDiagnostic &FirstNote, -                               SourceRange FirstParenRange, -                               const PartialDiagnostic &SecondNote, -                               SourceRange SecondParenRange) { -  Self.Diag(Loc, PD); - -  if (!FirstNote.getDiagID()) -    return; - -  SourceLocation EndLoc = Self.PP.getLocForEndOfToken(FirstParenRange.getEnd()); -  if (!FirstParenRange.getEnd().isFileID() || EndLoc.isInvalid()) { -    // We can't display the parentheses, so just return. -    return; -  } - -  Self.Diag(Loc, FirstNote) -    << FixItHint::CreateInsertion(FirstParenRange.getBegin(), "(") -    << FixItHint::CreateInsertion(EndLoc, ")"); - -  if (!SecondNote.getDiagID()) -    return; - -  EndLoc = Self.PP.getLocForEndOfToken(SecondParenRange.getEnd()); -  if (!SecondParenRange.getEnd().isFileID() || EndLoc.isInvalid()) { -    // We can't display the parentheses, so just dig the -    // warning/error and return. -    Self.Diag(Loc, SecondNote); -    return; -  } - -  Self.Diag(Loc, SecondNote) -    << FixItHint::CreateInsertion(SecondParenRange.getBegin(), "(") -    << FixItHint::CreateInsertion(EndLoc, ")"); -} -  /// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison  /// operators are mixed in a way that suggests that the programmer forgot that  /// comparison operators have higher precedence. The most typical example of @@ -9666,6 +9878,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,      *Complained = false;    // Decode the result (notice that AST's are still created for extensions). +  bool CheckInferredResultType = false;    bool isInvalid = false;    unsigned DiagKind;    FixItHint Hint; @@ -9682,6 +9895,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,    case IncompatiblePointer:      MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint);      DiagKind = diag::ext_typecheck_convert_incompatible_pointer; +    CheckInferredResultType = DstType->isObjCObjectPointerType() && +      SrcType->isObjCObjectPointerType();      break;    case IncompatiblePointerSign:      DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign; @@ -9763,6 +9978,9 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,    Diag(Loc, DiagKind) << FirstType << SecondType << Action      << SrcExpr->getSourceRange() << Hint; +  if (CheckInferredResultType) +    EmitRelatedResultTypeNote(SrcExpr); +      if (Complained)      *Complained = true;    return isInvalid; @@ -9914,26 +10132,25 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {    // Note that this declaration has been used.    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { -    unsigned TypeQuals; -    if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) { -      if (Constructor->getParent()->hasTrivialConstructor()) +    if (Constructor->isDefaulted() && Constructor->isDefaultConstructor()) { +      if (Constructor->isTrivial())          return;        if (!Constructor->isUsed(false))          DefineImplicitDefaultConstructor(Loc, Constructor); -    } else if (Constructor->isImplicit() && -               Constructor->isCopyConstructor(TypeQuals)) { +    } else if (Constructor->isDefaulted() && +               Constructor->isCopyConstructor()) {        if (!Constructor->isUsed(false)) -        DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals); +        DefineImplicitCopyConstructor(Loc, Constructor);      }      MarkVTableUsed(Loc, Constructor->getParent());    } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { -    if (Destructor->isImplicit() && !Destructor->isUsed(false)) +    if (Destructor->isDefaulted() && !Destructor->isUsed(false))        DefineImplicitDestructor(Loc, Destructor);      if (Destructor->isVirtual())        MarkVTableUsed(Loc, Destructor->getParent());    } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) { -    if (MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() && +    if (MethodDecl->isDefaulted() && MethodDecl->isOverloadedOperator() &&          MethodDecl->getOverloadedOperator() == OO_Equal) {        if (!MethodDecl->isUsed(false))          DefineImplicitCopyAssignment(Loc, MethodDecl); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp index 7f1bf596a237..2f5a890e51de 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp @@ -17,6 +17,7 @@  #include "clang/Sema/Lookup.h"  #include "clang/Sema/ParsedTemplate.h"  #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Scope.h"  #include "clang/Sema/TemplateDeduction.h"  #include "clang/AST/ASTContext.h"  #include "clang/AST/CXXInheritance.h" @@ -385,13 +386,14 @@ static UuidAttr *GetUuidAttrOfType(QualType QT) {    else if (QT->isArrayType())      Ty = cast<ArrayType>(QT)->getElementType().getTypePtr(); -  // Loop all class definition and declaration looking for an uuid attribute. +  // Loop all record redeclaration looking for an uuid attribute.    CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); -  while (RD) { -    if (UuidAttr *Uuid = RD->getAttr<UuidAttr>()) +  for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(), +       E = RD->redecls_end(); I != E; ++I) { +    if (UuidAttr *Uuid = I->getAttr<UuidAttr>())        return Uuid; -    RD = RD->getPreviousDeclaration();    } +    return 0;  } @@ -574,42 +576,54 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E) {    return Owned(E);  } -CXXMethodDecl *Sema::tryCaptureCXXThis() { +QualType Sema::getAndCaptureCurrentThisType() {    // Ignore block scopes: we can capture through them.    // Ignore nested enum scopes: we'll diagnose non-constant expressions    // where they're invalid, and other uses are legitimate.    // Don't ignore nested class scopes: you can't use 'this' in a local class.    DeclContext *DC = CurContext; +  unsigned NumBlocks = 0;    while (true) { -    if (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext(); -    else if (isa<EnumDecl>(DC)) DC = cast<EnumDecl>(DC)->getDeclContext(); +    if (isa<BlockDecl>(DC)) { +      DC = cast<BlockDecl>(DC)->getDeclContext(); +      ++NumBlocks; +    } else if (isa<EnumDecl>(DC)) +      DC = cast<EnumDecl>(DC)->getDeclContext();      else break;    } -  // If we're not in an instance method, error out. -  CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC); -  if (!method || !method->isInstance()) -    return 0; +  QualType ThisTy; +  if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) { +    if (method && method->isInstance()) +      ThisTy = method->getThisType(Context); +  } else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) { +    // C++0x [expr.prim]p4: +    //   Otherwise, if a member-declarator declares a non-static data member +    // of a class X, the expression this is a prvalue of type "pointer to X" +    // within the optional brace-or-equal-initializer. +    Scope *S = getScopeForContext(DC); +    if (!S || S->getFlags() & Scope::ThisScope) +      ThisTy = Context.getPointerType(Context.getRecordType(RD)); +  } -  // Mark that we're closing on 'this' in all the block scopes, if applicable. -  for (unsigned idx = FunctionScopes.size() - 1; -       isa<BlockScopeInfo>(FunctionScopes[idx]); -       --idx) -    cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true; +  // Mark that we're closing on 'this' in all the block scopes we ignored. +  if (!ThisTy.isNull()) +    for (unsigned idx = FunctionScopes.size() - 1; +         NumBlocks; --idx, --NumBlocks) +      cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true; -  return method; +  return ThisTy;  } -ExprResult Sema::ActOnCXXThis(SourceLocation loc) { +ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {    /// C++ 9.3.2: In the body of a non-static member function, the keyword this    /// is a non-lvalue expression whose value is the address of the object for    /// which the function is called. -  CXXMethodDecl *method = tryCaptureCXXThis(); -  if (!method) return Diag(loc, diag::err_invalid_this_use); +  QualType ThisTy = getAndCaptureCurrentThisType(); +  if (ThisTy.isNull()) return Diag(Loc, diag::err_invalid_this_use); -  return Owned(new (Context) CXXThisExpr(loc, method->getThisType(Context), -                                         /*isImplicit=*/false)); +  return Owned(new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false));  }  ExprResult @@ -950,8 +964,8 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,        }      } -    ArraySize = ImpCastExprToType(ArraySize, Context.getSizeType(), -                      CK_IntegralCast).take(); +    // Note that we do *not* convert the argument in any way.  It can +    // be signed, larger than size_t, whatever.    }    FunctionDecl *OperatorNew = 0; @@ -1326,11 +1340,12 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,  bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,                                    DeclarationName Name, Expr** Args,                                    unsigned NumArgs, DeclContext *Ctx, -                                  bool AllowMissing, FunctionDecl *&Operator) { +                                  bool AllowMissing, FunctionDecl *&Operator, +                                  bool Diagnose) {    LookupResult R(*this, Name, StartLoc, LookupOrdinaryName);    LookupQualifiedName(R, Ctx);    if (R.empty()) { -    if (AllowMissing) +    if (AllowMissing || !Diagnose)        return false;      return Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)        << Name << Range; @@ -1374,41 +1389,50 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,      // Watch out for variadic allocator function.      unsigned NumArgsInFnDecl = FnDecl->getNumParams();      for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) { +      InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, +                                                       FnDecl->getParamDecl(i)); + +      if (!Diagnose && !CanPerformCopyInitialization(Entity, Owned(Args[i]))) +        return true; +        ExprResult Result -        = PerformCopyInitialization(InitializedEntity::InitializeParameter( -                                                       Context, -                                                       FnDecl->getParamDecl(i)), -                                    SourceLocation(), -                                    Owned(Args[i])); +        = PerformCopyInitialization(Entity, SourceLocation(), Owned(Args[i]));        if (Result.isInvalid())          return true;        Args[i] = Result.takeAs<Expr>();      }      Operator = FnDecl; -    CheckAllocationAccess(StartLoc, Range, R.getNamingClass(), Best->FoundDecl); +    CheckAllocationAccess(StartLoc, Range, R.getNamingClass(), Best->FoundDecl, +                          Diagnose);      return false;    }    case OR_No_Viable_Function: -    Diag(StartLoc, diag::err_ovl_no_viable_function_in_call) -      << Name << Range; -    Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); +    if (Diagnose) { +      Diag(StartLoc, diag::err_ovl_no_viable_function_in_call) +        << Name << Range; +      Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); +    }      return true;    case OR_Ambiguous: -    Diag(StartLoc, diag::err_ovl_ambiguous_call) -      << Name << Range; -    Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); +    if (Diagnose) { +      Diag(StartLoc, diag::err_ovl_ambiguous_call) +        << Name << Range; +      Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); +    }      return true;    case OR_Deleted: { -    Diag(StartLoc, diag::err_ovl_deleted_call) -      << Best->Function->isDeleted() -      << Name  -      << getDeletedOrUnavailableSuffix(Best->Function) -      << Range; -    Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); +    if (Diagnose) { +      Diag(StartLoc, diag::err_ovl_deleted_call) +        << Best->Function->isDeleted() +        << Name  +        << getDeletedOrUnavailableSuffix(Best->Function) +        << Range; +      Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); +    }      return true;    }    } @@ -1568,7 +1592,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,  bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,                                      DeclarationName Name, -                                    FunctionDecl* &Operator) { +                                    FunctionDecl* &Operator, bool Diagnose) {    LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName);    // Try to find operator delete/operator delete[] in class scope.    LookupQualifiedName(Found, RD); @@ -1595,33 +1619,45 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,    // There's exactly one suitable operator;  pick it.    if (Matches.size() == 1) {      Operator = cast<CXXMethodDecl>(Matches[0]->getUnderlyingDecl()); + +    if (Operator->isDeleted()) { +      if (Diagnose) { +        Diag(StartLoc, diag::err_deleted_function_use); +        Diag(Operator->getLocation(), diag::note_unavailable_here) << true; +      } +      return true; +    } +      CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(), -                          Matches[0]); +                          Matches[0], Diagnose);      return false;    // We found multiple suitable operators;  complain about the ambiguity.    } else if (!Matches.empty()) { -    Diag(StartLoc, diag::err_ambiguous_suitable_delete_member_function_found) -      << Name << RD; - -    for (llvm::SmallVectorImpl<DeclAccessPair>::iterator -           F = Matches.begin(), FEnd = Matches.end(); F != FEnd; ++F) -      Diag((*F)->getUnderlyingDecl()->getLocation(), -           diag::note_member_declared_here) << Name; +    if (Diagnose) { +      Diag(StartLoc, diag::err_ambiguous_suitable_delete_member_function_found) +        << Name << RD; + +      for (llvm::SmallVectorImpl<DeclAccessPair>::iterator +             F = Matches.begin(), FEnd = Matches.end(); F != FEnd; ++F) +        Diag((*F)->getUnderlyingDecl()->getLocation(), +             diag::note_member_declared_here) << Name; +    }      return true;    }    // We did find operator delete/operator delete[] declarations, but    // none of them were suitable.    if (!Found.empty()) { -    Diag(StartLoc, diag::err_no_suitable_delete_member_function_found) -      << Name << RD; - -    for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); -         F != FEnd; ++F) -      Diag((*F)->getUnderlyingDecl()->getLocation(), -           diag::note_member_declared_here) << Name; - +    if (Diagnose) { +      Diag(StartLoc, diag::err_no_suitable_delete_member_function_found) +        << Name << RD; + +      for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); +           F != FEnd; ++F) +        Diag((*F)->getUnderlyingDecl()->getLocation(), +             diag::note_member_declared_here) << Name; +    }      return true;    } @@ -1633,8 +1669,8 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,    Expr* DeallocArgs[1];    DeallocArgs[0] = &Null;    if (FindAllocationOverload(StartLoc, SourceRange(), Name, -                             DeallocArgs, 1, TUDecl, /*AllowMissing=*/false, -                             Operator)) +                             DeallocArgs, 1, TUDecl, !Diagnose, +                             Operator, Diagnose))      return true;    assert(Operator && "Did not find a deallocation function!"); @@ -1780,6 +1816,20 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,                                      const_cast<CXXDestructorDecl*>(Dtor));            DiagnoseUseOfDecl(Dtor, StartLoc);          } + +      // C++ [expr.delete]p3: +      //   In the first alternative (delete object), if the static type of the +      //   object to be deleted is different from its dynamic type, the static +      //   type shall be a base class of the dynamic type of the object to be +      //   deleted and the static type shall have a virtual destructor or the +      //   behavior is undefined. +      // +      // Note: a final class cannot be derived from, no issue there +      if (!ArrayForm && RD->isPolymorphic() && !RD->hasAttr<FinalAttr>()) { +        CXXDestructorDecl *dtor = RD->getDestructor(); +        if (!dtor || !dtor->isVirtual()) +          Diag(StartLoc, diag::warn_delete_non_virtual_dtor) << PointeeElem; +      }      }      if (!OperatorDelete) { @@ -2174,7 +2224,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,    case ICK_Pointer_Conversion: {      if (SCS.IncompatibleObjC && Action != AA_Casting) {        // Diagnose incompatible Objective-C conversions -      if (Action == AA_Initializing) +      if (Action == AA_Initializing || Action == AA_Assigning)          Diag(From->getSourceRange().getBegin(),               diag::ext_typecheck_convert_incompatible_pointer)            << ToType << From->getType() << Action @@ -2184,6 +2234,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,               diag::ext_typecheck_convert_incompatible_pointer)            << From->getType() << ToType << Action            << From->getSourceRange(); +       +      if (From->getType()->isObjCObjectPointerType() && +          ToType->isObjCObjectPointerType()) +        EmitRelatedResultTypeNote(From);      }      CastKind Kind = CK_Invalid; @@ -2416,6 +2470,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,      // C++0x [meta.unary.prop] Table 49 requires the following traits to be      // applied to a complete type.    case UTT_IsTrivial: +  case UTT_IsTriviallyCopyable:    case UTT_IsStandardLayout:    case UTT_IsPOD:    case UTT_IsLiteral: @@ -2433,7 +2488,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,    case UTT_HasNothrowConstructor:    case UTT_HasNothrowCopy:    case UTT_HasTrivialAssign: -  case UTT_HasTrivialConstructor: +  case UTT_HasTrivialDefaultConstructor:    case UTT_HasTrivialCopy:    case UTT_HasTrivialDestructor:    case UTT_HasVirtualDestructor: @@ -2512,6 +2567,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,      return T.isVolatileQualified();    case UTT_IsTrivial:      return T->isTrivialType(); +  case UTT_IsTriviallyCopyable: +    return T->isTriviallyCopyableType();    case UTT_IsStandardLayout:      return T->isStandardLayoutType();    case UTT_IsPOD: @@ -2543,7 +2600,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,      //      //   1: http://gcc.gnu/.org/onlinedocs/gcc/Type-Traits.html      //   2: http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index -  case UTT_HasTrivialConstructor: +  case UTT_HasTrivialDefaultConstructor:      // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:      //   If __is_pod (type) is true then the trait is true, else if type is      //   a cv class or union type (or array thereof) with a trivial default @@ -2552,7 +2609,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,        return true;      if (const RecordType *RT =            C.getBaseElementType(T)->getAs<RecordType>()) -      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialConstructor(); +      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDefaultConstructor();      return false;    case UTT_HasTrivialCopy:      // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: @@ -2619,7 +2676,6 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,          return true;        bool FoundAssign = false; -      bool AllNoThrow = true;        DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal);        LookupResult Res(Self, DeclarationNameInfo(Name, KeyLoc),                         Sema::LookupOrdinaryName); @@ -2631,15 +2687,15 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,              FoundAssign = true;              const FunctionProtoType *CPT                  = Operator->getType()->getAs<FunctionProtoType>(); -            if (!CPT->isNothrow(Self.Context)) { -              AllNoThrow = false; -              break; -            } +            if (CPT->getExceptionSpecType() == EST_Delayed) +              return false; +            if (!CPT->isNothrow(Self.Context)) +              return false;            }          }        } -      return FoundAssign && AllNoThrow; +      return FoundAssign;      }      return false;    case UTT_HasNothrowCopy: @@ -2656,7 +2712,6 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,          return true;        bool FoundConstructor = false; -      bool AllNoThrow = true;        unsigned FoundTQs;        DeclContext::lookup_const_iterator Con, ConEnd;        for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD); @@ -2671,16 +2726,16 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,            FoundConstructor = true;            const FunctionProtoType *CPT                = Constructor->getType()->getAs<FunctionProtoType>(); +          if (CPT->getExceptionSpecType() == EST_Delayed) +            return false;            // FIXME: check whether evaluating default arguments can throw.            // For now, we'll be conservative and assume that they can throw. -          if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1) { -            AllNoThrow = false; -            break; -          } +          if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1) +            return false;          }        } -      return FoundConstructor && AllNoThrow; +      return FoundConstructor;      }      return false;    case UTT_HasNothrowConstructor: @@ -2693,7 +2748,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,        return true;      if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) {        CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); -      if (RD->hasTrivialConstructor()) +      if (RD->hasTrivialDefaultConstructor())          return true;        DeclContext::lookup_const_iterator Con, ConEnd; @@ -2706,6 +2761,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,          if (Constructor->isDefaultConstructor()) {            const FunctionProtoType *CPT                = Constructor->getType()->getAs<FunctionProtoType>(); +          if (CPT->getExceptionSpecType() == EST_Delayed) +            return false;            // TODO: check whether evaluating default arguments can throw.            // For now, we'll be conservative and assume that they can throw.            return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0; @@ -2852,7 +2909,7 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,      Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true);      Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl());      InitializationSequence Init(Self, To, Kind, &FromPtr, 1); -    if (Init.getKind() == InitializationSequence::FailedSequence) +    if (Init.Failed())        return false;      ExprResult Result = Init.Perform(Self, To, Kind, MultiExprArg(&FromPtr, 1)); @@ -3213,7 +3270,7 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,        if (TTy.isAtLeastAsQualifiedAs(FTy)) {          InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy);          InitializationSequence InitSeq(Self, Entity, Kind, &From, 1); -        if (InitSeq.getKind() != InitializationSequence::FailedSequence) { +        if (InitSeq) {            HaveConversion = true;            return false;          } @@ -3238,7 +3295,7 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,    InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy);    InitializationSequence InitSeq(Self, Entity, Kind, &From, 1); -  HaveConversion = InitSeq.getKind() != InitializationSequence::FailedSequence; +  HaveConversion = !InitSeq.Failed();    ToType = TTy;    if (InitSeq.isAmbiguous())      return InitSeq.Diagnose(Self, Entity, Kind, &From, 1); @@ -4295,3 +4352,18 @@ StmtResult Sema::ActOnFinishFullStmt(Stmt *FullStmt) {    return MaybeCreateStmtWithCleanups(FullStmt);  } + +bool Sema::CheckMicrosoftIfExistsSymbol(CXXScopeSpec &SS, +                                        UnqualifiedId &Name) { +  DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name); +  DeclarationName TargetName = TargetNameInfo.getName(); +  if (!TargetName) +    return false; + +  // Do the redeclaration lookup in the current scope. +  LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName, +                 Sema::NotForRedeclaration); +  R.suppressDiagnostics(); +  LookupParsedName(R, getCurScope(), &SS); +  return !R.empty();  +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp index 2a262f093922..cb5c1e0d0cbe 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp @@ -119,7 +119,7 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,    return new (Context) ObjCStringLiteral(S, Ty, AtLocs[0]);  } -Expr *Sema::BuildObjCEncodeExpression(SourceLocation AtLoc, +ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,                                        TypeSourceInfo *EncodedTypeInfo,                                        SourceLocation RParenLoc) {    QualType EncodedType = EncodedTypeInfo->getType(); @@ -127,6 +127,12 @@ Expr *Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,    if (EncodedType->isDependentType())      StrTy = Context.DependentTy;    else { +    if (!EncodedType->getAsArrayTypeUnsafe()) // Incomplete array is handled. +      if (RequireCompleteType(AtLoc, EncodedType, +                         PDiag(diag::err_incomplete_type_objc_at_encode) +                             << EncodedTypeInfo->getTypeLoc().getSourceRange())) +        return ExprError(); +      std::string Str;      Context.getObjCEncodingForType(EncodedType, Str); @@ -235,10 +241,72 @@ ObjCMethodDecl *Sema::tryCaptureObjCSelf() {    return method;  } +QualType Sema::getMessageSendResultType(QualType ReceiverType, +                                        ObjCMethodDecl *Method, +                                    bool isClassMessage, bool isSuperMessage) { +  assert(Method && "Must have a method"); +  if (!Method->hasRelatedResultType()) +    return Method->getSendResultType(); +   +  // If a method has a related return type: +  //   - if the method found is an instance method, but the message send +  //     was a class message send, T is the declared return type of the method +  //     found +  if (Method->isInstanceMethod() && isClassMessage) +    return Method->getSendResultType(); +   +  //   - if the receiver is super, T is a pointer to the class of the  +  //     enclosing method definition +  if (isSuperMessage) { +    if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) +      if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) +        return Context.getObjCObjectPointerType( +                                        Context.getObjCInterfaceType(Class)); +  } +     +  //   - if the receiver is the name of a class U, T is a pointer to U +  if (ReceiverType->getAs<ObjCInterfaceType>() || +      ReceiverType->isObjCQualifiedInterfaceType()) +    return Context.getObjCObjectPointerType(ReceiverType); +  //   - if the receiver is of type Class or qualified Class type,  +  //     T is the declared return type of the method. +  if (ReceiverType->isObjCClassType() || +      ReceiverType->isObjCQualifiedClassType()) +    return  Method->getSendResultType(); +   +  //   - if the receiver is id, qualified id, Class, or qualified Class, T +  //     is the receiver type, otherwise +  //   - T is the type of the receiver expression. +  return ReceiverType; +} + +void Sema::EmitRelatedResultTypeNote(const Expr *E) { +  E = E->IgnoreParenImpCasts(); +  const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(E); +  if (!MsgSend) +    return; +   +  const ObjCMethodDecl *Method = MsgSend->getMethodDecl(); +  if (!Method) +    return; +   +  if (!Method->hasRelatedResultType()) +    return; +   +  if (Context.hasSameUnqualifiedType(Method->getResultType() +                                                        .getNonReferenceType(), +                                     MsgSend->getType())) +    return; +   +  Diag(Method->getLocation(), diag::note_related_result_type_inferred) +    << Method->isInstanceMethod() << Method->getSelector() +    << MsgSend->getType(); +} -bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, +bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, +                                     Expr **Args, unsigned NumArgs,                                       Selector Sel, ObjCMethodDecl *Method, -                                     bool isClassMessage, +                                     bool isClassMessage, bool isSuperMessage,                                       SourceLocation lbrac, SourceLocation rbrac,                                       QualType &ReturnType, ExprValueKind &VK) {    if (!Method) { @@ -262,7 +330,8 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,      return false;    } -  ReturnType = Method->getSendResultType(); +  ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage,  +                                        isSuperMessage);    VK = Expr::getValueKindForType(Method->getResultType());    unsigned NumNamedArgs = Sel.getNumArgs(); @@ -450,9 +519,12 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,      ResTy = ResTy.getNonLValueExprType(Context);      Selector Sel = PP.getSelectorTable().getNullarySelector(Member);      ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); -    if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc)) -      ResTy = Getter->getResultType(); - +    if (Getter && +        (Getter->hasRelatedResultType() +         || DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc))) +        ResTy = getMessageSendResultType(QualType(OPT, 0), Getter, false,  +                                         Super); +                   if (Super)        return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,                                                       VK_LValue, OK_ObjCProperty, @@ -470,14 +542,18 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,        // Check whether we can reference this property.        if (DiagnoseUseOfDecl(PD, MemberLoc))          return ExprError(); +       +      QualType T = PD->getType(); +      if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) +        T = getMessageSendResultType(QualType(OPT, 0), Getter, false, Super);        if (Super) -        return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), +        return Owned(new (Context) ObjCPropertyRefExpr(PD, T,                                                         VK_LValue,                                                         OK_ObjCProperty,                                                         MemberLoc,                                                          SuperLoc, SuperType));        else -        return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), +        return Owned(new (Context) ObjCPropertyRefExpr(PD, T,                                                         VK_LValue,                                                         OK_ObjCProperty,                                                         MemberLoc, @@ -534,7 +610,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,    if (Getter || Setter) {      QualType PType;      if (Getter) -      PType = Getter->getSendResultType(); +      PType = getMessageSendResultType(QualType(OPT, 0), Getter, false, Super);      else {        ParmVarDecl *ArgDecl = *Setter->param_begin();        PType = ArgDecl->getType(); @@ -608,10 +684,14 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,    IdentifierInfo *receiverNamePtr = &receiverName;    ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr,                                                    receiverNameLoc); + +  bool IsSuper = false;    if (IFace == 0) {      // If the "receiver" is 'super' in a method, handle it as an expression-like      // property reference.      if (receiverNamePtr->isStr("super")) { +      IsSuper = true; +        if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf()) {          if (CurMethod->isInstanceMethod()) {            QualType T =  @@ -680,7 +760,9 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,      ExprValueKind VK = VK_LValue;      if (Getter) { -      PType = Getter->getSendResultType(); +      PType = getMessageSendResultType(Context.getObjCInterfaceType(IFace), +                                       Getter, true,  +                                       receiverNamePtr->isStr("super"));        if (!getLangOptions().CPlusPlus &&            !PType.hasQualifiers() && PType->isVoidType())          VK = VK_RValue; @@ -693,6 +775,13 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,      ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty); +    if (IsSuper) +    return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, +                                                   PType, VK, OK, +                                                   propertyNameLoc, +                                                   receiverNameLoc,  +                                          Context.getObjCInterfaceType(IFace))); +      return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,                                                     PType, VK, OK,                                                     propertyNameLoc, @@ -949,8 +1038,9 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,    unsigned NumArgs = ArgsIn.size();    Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); -  if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, true, -                                LBracLoc, RBracLoc, ReturnType, VK)) +  if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, Method, true, +                                SuperLoc.isValid(), LBracLoc, RBracLoc,  +                                ReturnType, VK))      return ExprError();    if (Method && !Method->getResultType()->isVoidType() && @@ -1232,7 +1322,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,    ExprValueKind VK = VK_RValue;    bool ClassMessage = (ReceiverType->isObjCClassType() ||                         ReceiverType->isObjCQualifiedClassType()); -  if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, ClassMessage, +  if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, Method,  +                                ClassMessage, SuperLoc.isValid(),                                   LBracLoc, RBracLoc, ReturnType, VK))      return ExprError(); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp index ca3fd6dfcb45..a33f5d0b2f3e 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp @@ -296,8 +296,7 @@ void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,        // Do nothing      } else if (Init < NumInits) {        ILE->setInit(Init, MemberInit.takeAs<Expr>()); -    } else if (InitSeq.getKind() -                 == InitializationSequence::ConstructorInitialization) { +    } else if (InitSeq.isConstructorInitialization()) {        // 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 @@ -418,8 +417,7 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,            return;          } -        if (InitSeq.getKind() -                   == InitializationSequence::ConstructorInitialization) { +        if (InitSeq.isConstructorInitialization()) {            // 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 @@ -2137,7 +2135,7 @@ bool InitializationSequence::isDirectReferenceBinding() const {  }  bool InitializationSequence::isAmbiguous() const { -  if (getKind() != FailedSequence) +  if (!Failed())      return false;    switch (getFailureKind()) { @@ -2310,7 +2308,7 @@ void InitializationSequence::AddArrayInitStep(QualType T) {  void InitializationSequence::SetOverloadFailure(FailureKind Failure,                                                  OverloadingResult Result) { -  SequenceKind = FailedSequence; +  setSequenceKind(FailedSequence);    this->Failure = Failure;    this->FailedOverloadResult = Result;  } @@ -2331,7 +2329,6 @@ static void TryListInitialization(Sema &S,    // well-formed. When we actually "perform" list initialization, we'll    // do all of the necessary checking.  C++0x initializer lists will    // force us to perform more checking here. -  Sequence.setSequenceKind(InitializationSequence::ListInitialization);    QualType DestType = Entity.getType(); @@ -2800,7 +2797,6 @@ static void TryStringLiteralInitialization(Sema &S,                                             const InitializationKind &Kind,                                             Expr *Initializer,                                         InitializationSequence &Sequence) { -  Sequence.setSequenceKind(InitializationSequence::StringInit);    Sequence.AddStringInitStep(Entity.getType());  } @@ -2813,8 +2809,6 @@ static void TryConstructorInitialization(Sema &S,                                           Expr **Args, unsigned NumArgs,                                           QualType DestType,                                           InitializationSequence &Sequence) { -  Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization); -    // Build the candidate set directly in the initialization sequence    // structure, so that it will persist if we fail.    OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); @@ -2947,7 +2941,6 @@ static void TryValueInitialization(Sema &S,    }    Sequence.AddZeroInitializationStep(Entity.getType()); -  Sequence.setSequenceKind(InitializationSequence::ZeroInitialization);  }  /// \brief Attempt default initialization (C++ [dcl.init]p6). @@ -2973,7 +2966,6 @@ static void TryDefaultInitialization(Sema &S,    }    //     - 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 @@ -2990,8 +2982,6 @@ static void TryUserDefinedConversion(Sema &S,                                       const InitializationKind &Kind,                                       Expr *Initializer,                                       InitializationSequence &Sequence) { -  Sequence.setSequenceKind(InitializationSequence::UserDefinedConversion); -    QualType DestType = Entity.getType();    assert(!DestType->isReferenceType() && "References are handled elsewhere");    QualType SourceType = Initializer->getType(); @@ -3176,6 +3166,9 @@ InitializationSequence::InitializationSequence(Sema &S,      return;    } +  // Almost everything is a normal sequence. +  setSequenceKind(NormalSequence); +    for (unsigned I = 0; I != NumArgs; ++I)      if (Args[I]->getObjectKind() == OK_ObjCProperty) {        ExprResult Result = S.ConvertPropertyForRValue(Args[I]); @@ -3252,7 +3245,6 @@ InitializationSequence::InitializationSequence(Sema &S,        else if (Initializer->HasSideEffects(S.Context))          SetFailed(FK_NonConstantArrayInit);        else { -        setSequenceKind(ArrayInit);          AddArrayInitStep(DestType);        }      } else if (DestAT->getElementType()->isAnyCharacterType()) @@ -3265,7 +3257,6 @@ InitializationSequence::InitializationSequence(Sema &S,    // Handle initialization in C    if (!S.getLangOptions().CPlusPlus) { -    setSequenceKind(CAssignment);      AddCAssignmentStep(DestType);      return;    } @@ -3325,8 +3316,6 @@ InitializationSequence::InitializationSequence(Sema &S,      else        SetFailed(InitializationSequence::FK_ConversionFailed);    } -  else -    setSequenceKind(StandardConversion);  }  InitializationSequence::~InitializationSequence() { @@ -3650,13 +3639,13 @@ InitializationSequence::Perform(Sema &S,                                  const InitializationKind &Kind,                                  MultiExprArg Args,                                  QualType *ResultType) { -  if (SequenceKind == FailedSequence) { +  if (Failed()) {      unsigned NumArgs = Args.size();      Diagnose(S, Entity, Kind, (Expr **)Args.release(), NumArgs);      return ExprError();    } -  if (SequenceKind == DependentSequence) { +  if (getKind() == DependentSequence) {      // 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. @@ -3710,7 +3699,8 @@ InitializationSequence::Perform(Sema &S,                                                   SourceLocation()));    } -  if (SequenceKind == NoInitialization) +  // No steps means no initialization. +  if (Steps.empty())      return S.Owned((Expr *)0);    QualType DestType = Entity.getType().getNonReferenceType(); @@ -3723,8 +3713,6 @@ InitializationSequence::Perform(Sema &S,    ExprResult 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. @@ -4019,8 +4007,9 @@ InitializationSequence::Perform(Sema &S,          // the definition for completely trivial constructors.          CXXRecordDecl *ClassDecl = Constructor->getParent();          assert(ClassDecl && "No parent class for constructor."); -        if (Constructor->isImplicit() && Constructor->isDefaultConstructor() && -            ClassDecl->hasTrivialConstructor() && !Constructor->isUsed(false)) +        if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() && +            ClassDecl->hasTrivialDefaultConstructor() && +            !Constructor->isUsed(false))            S.DefineImplicitDefaultConstructor(Loc, Constructor);        } @@ -4060,8 +4049,7 @@ InitializationSequence::Perform(Sema &S,            ConstructKind = Entity.getBaseSpecifier()->isVirtual() ?              CXXConstructExpr::CK_VirtualBase :              CXXConstructExpr::CK_NonVirtualBase; -        } -        if (Entity.getKind() == InitializedEntity::EK_Delegating) { +        } else if (Entity.getKind() == InitializedEntity::EK_Delegating) {            ConstructKind = CXXConstructExpr::CK_Delegating;          } @@ -4216,7 +4204,7 @@ bool InitializationSequence::Diagnose(Sema &S,                                        const InitializedEntity &Entity,                                        const InitializationKind &Kind,                                        Expr **Args, unsigned NumArgs) { -  if (SequenceKind != FailedSequence) +  if (!Failed())      return false;    QualType DestType = Entity.getType(); @@ -4334,6 +4322,9 @@ bool InitializationSequence::Diagnose(Sema &S,        << Args[0]->isLValue()        << Args[0]->getType()        << Args[0]->getSourceRange(); +    if (DestType.getNonReferenceType()->isObjCObjectPointerType() && +        Args[0]->getType()->isObjCObjectPointerType()) +      S.EmitRelatedResultTypeNote(Args[0]);      break;    case FK_ConversionFailed: { @@ -4344,6 +4335,9 @@ bool InitializationSequence::Diagnose(Sema &S,        << Args[0]->isLValue()        << FromType        << Args[0]->getSourceRange(); +    if (DestType.getNonReferenceType()->isObjCObjectPointerType() && +        Args[0]->getType()->isObjCObjectPointerType()) +      S.EmitRelatedResultTypeNote(Args[0]);      break;    } @@ -4587,48 +4581,16 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {    }    case DependentSequence: -    OS << "Dependent sequence: "; +    OS << "Dependent sequence\n";      return; -  case UserDefinedConversion: -    OS << "User-defined conversion sequence: "; -    break; - -  case ConstructorInitialization: -    OS << "Constructor initialization sequence: "; +  case NormalSequence: +    OS << "Normal sequence: ";      break;    case ReferenceBinding:      OS << "Reference binding: ";      break; - -  case ListInitialization: -    OS << "List initialization: "; -    break; - -  case ZeroInitialization: -    OS << "Zero initialization\n"; -    return; - -  case NoInitialization: -    OS << "No initialization\n"; -    return; - -  case StandardConversion: -    OS << "Standard conversion: "; -    break; - -  case CAssignment: -    OS << "C assignment: "; -    break; - -  case StringInit: -    OS << "String initialization: "; -    break; - -  case ArrayInit: -    OS << "Array initialization: "; -    break;    }    for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) { @@ -4723,6 +4685,21 @@ void InitializationSequence::dump() const {  //===----------------------------------------------------------------------===//  // Initialization helper functions  //===----------------------------------------------------------------------===// +bool +Sema::CanPerformCopyInitialization(const InitializedEntity &Entity, +                                   ExprResult Init) { +  if (Init.isInvalid()) +    return false; + +  Expr *InitE = Init.get(); +  assert(InitE && "No initialization expression"); + +  InitializationKind Kind = InitializationKind::CreateCopy(SourceLocation(), +                                                           SourceLocation()); +  InitializationSequence Seq(*this, Entity, Kind, &InitE, 1); +  return !Seq.Failed(); +} +  ExprResult  Sema::PerformCopyInitialization(const InitializedEntity &Entity,                                  SourceLocation EqualLoc, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp index 309c7712d4cc..92ade1efcf01 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -14,6 +14,7 @@  #include "clang/Sema/Sema.h"  #include "clang/Sema/SemaInternal.h"  #include "clang/Sema/Lookup.h" +#include "clang/Sema/Overload.h"  #include "clang/Sema/DeclSpec.h"  #include "clang/Sema/Scope.h"  #include "clang/Sema/ScopeInfo.h" @@ -534,7 +535,7 @@ void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {      return;    // If the default constructor has not yet been declared, do so now. -  if (!Class->hasDeclaredDefaultConstructor()) +  if (Class->needsImplicitDefaultConstructor())      DeclareImplicitDefaultConstructor(Class);    // If the copy constructor has not yet been declared, do so now. @@ -581,7 +582,7 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S,      if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))        if (Record->getDefinition() &&            CanDeclareSpecialMemberFunction(S.Context, Record)) { -        if (!Record->hasDeclaredDefaultConstructor()) +        if (Record->needsImplicitDefaultConstructor())            S.DeclareImplicitDefaultConstructor(                                             const_cast<CXXRecordDecl *>(Record));          if (!Record->hasDeclaredCopyConstructor()) @@ -2136,11 +2137,200 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,    }  } +Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *D, +                                                            CXXSpecialMember SM, +                                                            bool ConstArg, +                                                            bool VolatileArg, +                                                            bool RValueThis, +                                                            bool ConstThis, +                                                            bool VolatileThis) { +  D = D->getDefinition(); +  assert((D && !D->isBeingDefined()) && +         "doing special member lookup into record that isn't fully complete"); +  if (RValueThis || ConstThis || VolatileThis) +    assert((SM == CXXCopyAssignment || SM == CXXMoveAssignment) && +           "constructors and destructors always have unqualified lvalue this"); +  if (ConstArg || VolatileArg) +    assert((SM != CXXDefaultConstructor && SM != CXXDestructor) && +           "parameter-less special members can't have qualified arguments"); + +  llvm::FoldingSetNodeID ID; +  ID.AddPointer(D); +  ID.AddInteger(SM); +  ID.AddInteger(ConstArg); +  ID.AddInteger(VolatileArg); +  ID.AddInteger(RValueThis); +  ID.AddInteger(ConstThis); +  ID.AddInteger(VolatileThis); + +  void *InsertPoint; +  SpecialMemberOverloadResult *Result = +    SpecialMemberCache.FindNodeOrInsertPos(ID, InsertPoint); + +  // This was already cached +  if (Result) +    return Result; + +  Result = BumpAlloc.Allocate<SpecialMemberOverloadResult>(); +  Result = new (Result) SpecialMemberOverloadResult(ID); +  SpecialMemberCache.InsertNode(Result, InsertPoint); + +  if (SM == CXXDestructor) { +    if (!D->hasDeclaredDestructor()) +      DeclareImplicitDestructor(D); +    CXXDestructorDecl *DD = D->getDestructor(); +    assert(DD && "record without a destructor"); +    Result->setMethod(DD); +    Result->setSuccess(DD->isDeleted()); +    Result->setConstParamMatch(false); +    return Result; +  } + +  // Prepare for overload resolution. Here we construct a synthetic argument +  // if necessary and make sure that implicit functions are declared. +  CanQualType CanTy = Context.getCanonicalType(Context.getTagDeclType(D)); +  DeclarationName Name; +  Expr *Arg = 0; +  unsigned NumArgs; + +  if (SM == CXXDefaultConstructor) { +    Name = Context.DeclarationNames.getCXXConstructorName(CanTy); +    NumArgs = 0; +    if (D->needsImplicitDefaultConstructor()) +      DeclareImplicitDefaultConstructor(D); +  } else { +    if (SM == CXXCopyConstructor || SM == CXXMoveConstructor) { +      Name = Context.DeclarationNames.getCXXConstructorName(CanTy); +      if (!D->hasDeclaredCopyConstructor()) +        DeclareImplicitCopyConstructor(D); +      // TODO: Move constructors +    } else { +      Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); +      if (!D->hasDeclaredCopyAssignment()) +        DeclareImplicitCopyAssignment(D); +      // TODO: Move assignment +    } + +    QualType ArgType = CanTy; +    if (ConstArg) +      ArgType.addConst(); +    if (VolatileArg) +      ArgType.addVolatile(); + +    // This isn't /really/ specified by the standard, but it's implied +    // we should be working from an RValue in the case of move to ensure +    // that we prefer to bind to rvalue references, and an LValue in the +    // case of copy to ensure we don't bind to rvalue references. +    // Possibly an XValue is actually correct in the case of move, but +    // there is no semantic difference for class types in this restricted +    // case. +    ExprValueKind VK; +    if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) +      VK = VK_LValue; +    else +      VK = VK_RValue; + +    NumArgs = 1; +    Arg = new (Context) OpaqueValueExpr(SourceLocation(), ArgType, VK); +  } + +  // Create the object argument +  QualType ThisTy = CanTy; +  if (ConstThis) +    ThisTy.addConst(); +  if (VolatileThis) +    ThisTy.addVolatile(); +  Expr::Classification ObjectClassification = +    (new (Context) OpaqueValueExpr(SourceLocation(), ThisTy, +                                   RValueThis ? VK_RValue : VK_LValue))-> +        Classify(Context); + +  // Now we perform lookup on the name we computed earlier and do overload +  // resolution. Lookup is only performed directly into the class since there +  // will always be a (possibly implicit) declaration to shadow any others. +  OverloadCandidateSet OCS((SourceLocation())); +  DeclContext::lookup_iterator I, E; +  Result->setConstParamMatch(false); + +  llvm::tie(I, E) = D->lookup(Name); +  assert((I != E) && +         "lookup for a constructor or assignment operator was empty"); +  for ( ; I != E; ++I) { +    if ((*I)->isInvalidDecl()) +      continue; + +    if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(*I)) { +      AddOverloadCandidate(M, DeclAccessPair::make(M, AS_public), &Arg, NumArgs, +                           OCS, true); + +      // Here we're looking for a const parameter to speed up creation of +      // implicit copy methods. +      if ((SM == CXXCopyAssignment && M->isCopyAssignmentOperator()) || +          (SM == CXXCopyConstructor && +            cast<CXXConstructorDecl>(M)->isCopyConstructor())) { +        QualType ArgType = M->getType()->getAs<FunctionProtoType>()->getArgType(0); +        if (ArgType->getPointeeType().isConstQualified()) +          Result->setConstParamMatch(true); +      } +    } else { +      FunctionTemplateDecl *Tmpl = cast<FunctionTemplateDecl>(*I); +      AddTemplateOverloadCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public), +                                   0, &Arg, NumArgs, OCS, true); +    } +  } + +  OverloadCandidateSet::iterator Best; +  switch (OCS.BestViableFunction(*this, SourceLocation(), Best)) { +    case OR_Success: +      Result->setMethod(cast<CXXMethodDecl>(Best->Function)); +      Result->setSuccess(true); +      break; + +    case OR_Deleted: +      Result->setMethod(cast<CXXMethodDecl>(Best->Function)); +      Result->setSuccess(false); +      break; + +    case OR_Ambiguous: +    case OR_No_Viable_Function: +      Result->setMethod(0); +      Result->setSuccess(false); +      break; +  } + +  return Result; +} + +/// \brief Look up the default constructor for the given class. +CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) { +  SpecialMemberOverloadResult *Result = +    LookupSpecialMember(Class, CXXDefaultConstructor, false, false, false, +                        false, false); + +  return cast_or_null<CXXConstructorDecl>(Result->getMethod()); +} + +/// \brief Look up the copy constructor for the given class. +CXXConstructorDecl *Sema::LookupCopyConstructor(CXXRecordDecl *Class, +                                                unsigned Quals, +                                                bool *ConstParamMatch) { +  assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) && +         "non-const, non-volatile qualifiers for copy ctor arg"); +  SpecialMemberOverloadResult *Result = +    LookupSpecialMember(Class, CXXCopyConstructor, Quals & Qualifiers::Const, +                        Quals & Qualifiers::Volatile, false, false, false); + +  if (ConstParamMatch) +    *ConstParamMatch = Result->hasConstParamMatch(); + +  return cast_or_null<CXXConstructorDecl>(Result->getMethod()); +} +  /// \brief Look up the constructors for the given class.  DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) { -  // If the copy constructor has not yet been declared, do so now. +  // If the implicit constructors have not yet been declared, do so now.    if (CanDeclareSpecialMemberFunction(Context, Class)) { -    if (!Class->hasDeclaredDefaultConstructor()) +    if (Class->needsImplicitDefaultConstructor())        DeclareImplicitDefaultConstructor(Class);      if (!Class->hasDeclaredCopyConstructor())        DeclareImplicitCopyConstructor(Class); @@ -2158,12 +2348,9 @@ DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {  ///  /// \returns The destructor for this class.  CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { -  // If the destructor has not yet been declared, do so now. -  if (CanDeclareSpecialMemberFunction(Context, Class) && -      !Class->hasDeclaredDestructor()) -    DeclareImplicitDestructor(Class); - -  return Class->getDestructor(); +  return cast<CXXDestructorDecl>(LookupSpecialMember(Class, CXXDestructor, +                                                     false, false, false, +                                                     false, false)->getMethod());  }  void ADLResult::insert(NamedDecl *New) { @@ -2410,8 +2597,8 @@ VisibleDeclsRecord::ShadowMapEntry::end() {    if (DeclOrVector.isNull())      return 0; -  if (DeclOrVector.dyn_cast<NamedDecl *>()) -    return &reinterpret_cast<NamedDecl*&>(DeclOrVector) + 1; +  if (DeclOrVector.is<NamedDecl *>()) +    return DeclOrVector.getAddrOf<NamedDecl *>() + 1;    return DeclOrVector.get<DeclVector *>()->end();  } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp index 3f3ed0e1f902..4bba6f8877bf 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp @@ -1628,6 +1628,15 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,      return true;    } +  // MSVC allows implicit function to void* type conversion. +  if (getLangOptions().Microsoft && FromPointeeType->isFunctionType() && +      ToPointeeType->isVoidType()) { +    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, +                                                       ToPointeeType, +                                                       ToType, Context); +    return true; +  } +    // When we're overloading in C, we allow a special kind of pointer    // conversion for compatible-but-not-identical pointee types.    if (!getLangOptions().CPlusPlus && @@ -2197,6 +2206,13 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,      Qualifiers FromQuals = FromType.getQualifiers();      Qualifiers ToQuals = ToType.getQualifiers(); +    // Allow addition/removal of GC attributes but not changing GC attributes. +    if (FromQuals.getObjCGCAttr() != ToQuals.getObjCGCAttr() && +        (!FromQuals.hasObjCGCAttr() || !ToQuals.hasObjCGCAttr())) { +      FromQuals.removeObjCGCAttr(); +      ToQuals.removeObjCGCAttr(); +    } +          //   -- for every j > 0, if const is in cv 1,j then const is in cv      //      2,j, and similarly for volatile.      if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals)) @@ -2507,12 +2523,10 @@ compareStandardConversionSubsets(ASTContext &Context,    // the identity conversion sequence is considered to be a subsequence of    // any non-identity conversion sequence -  if (SCS1.ReferenceBinding == SCS2.ReferenceBinding) { -    if (SCS1.isIdentityConversion() && !SCS2.isIdentityConversion()) -      return ImplicitConversionSequence::Better; -    else if (!SCS1.isIdentityConversion() && SCS2.isIdentityConversion()) -      return ImplicitConversionSequence::Worse; -  } +  if (SCS1.isIdentityConversion() && !SCS2.isIdentityConversion()) +    return ImplicitConversionSequence::Better; +  else if (!SCS1.isIdentityConversion() && SCS2.isIdentityConversion()) +    return ImplicitConversionSequence::Worse;    if (SCS1.Second != SCS2.Second) {      if (SCS1.Second == ICK_Identity) @@ -4689,6 +4703,10 @@ class BuiltinCandidateTypeSet  {    /// were present in the candidate set.    bool HasArithmeticOrEnumeralTypes; +  /// \brief A flag indicating whether the nullptr type was present in the +  /// candidate set. +  bool HasNullPtrType; +      /// Sema - The semantic analysis instance where we are building the    /// candidate type set.    Sema &SemaRef; @@ -4707,6 +4725,7 @@ public:    BuiltinCandidateTypeSet(Sema &SemaRef)      : HasNonRecordTypes(false),        HasArithmeticOrEnumeralTypes(false), +      HasNullPtrType(false),        SemaRef(SemaRef),        Context(SemaRef.Context) { } @@ -4739,6 +4758,7 @@ public:    bool hasNonRecordTypes() { return HasNonRecordTypes; }    bool hasArithmeticOrEnumeralTypes() { return HasArithmeticOrEnumeralTypes; } +  bool hasNullPtrType() const { return HasNullPtrType; }  };  /// AddPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty to @@ -4899,6 +4919,8 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,      // extension.      HasArithmeticOrEnumeralTypes = true;      VectorTypes.insert(Ty); +  } else if (Ty->isNullPtrType()) { +    HasNullPtrType = true;    } else if (AllowUserConversions && TyRec) {      // No conversion functions in incomplete types.      if (SemaRef.RequireCompleteType(Loc, Ty, 0)) @@ -5358,8 +5380,8 @@ public:    // C++ [over.built]p15:    // -  //   For every pointer or enumeration type T, there exist -  //   candidate operator functions of the form +  //   For every T, where T is an enumeration type, a pointer type, or  +  //   std::nullptr_t, there exist candidate operator functions of the form    //    //        bool       operator<(T, T);    //        bool       operator>(T, T); @@ -5444,6 +5466,17 @@ public:          S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2,                                CandidateSet);        } +       +      if (CandidateTypes[ArgIdx].hasNullPtrType()) { +        CanQualType NullPtrTy = S.Context.getCanonicalType(S.Context.NullPtrTy); +        if (AddedTypes.insert(NullPtrTy) && +            !UserDefinedBinaryOperators.count(std::make_pair(NullPtrTy,  +                                                             NullPtrTy))) { +          QualType ParamTypes[2] = { NullPtrTy, NullPtrTy }; +          S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2,  +                                CandidateSet); +        } +      }      }    } @@ -6401,7 +6434,9 @@ enum OverloadCandidateKind {    oc_constructor_template,    oc_implicit_default_constructor,    oc_implicit_copy_constructor, +  oc_implicit_move_constructor,    oc_implicit_copy_assignment, +  oc_implicit_move_assignment,    oc_implicit_inherited_constructor  }; @@ -6423,8 +6458,15 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,      if (Ctor->getInheritedConstructor())        return oc_implicit_inherited_constructor; -    return Ctor->isCopyConstructor() ? oc_implicit_copy_constructor -                                     : oc_implicit_default_constructor; +    if (Ctor->isDefaultConstructor()) +      return oc_implicit_default_constructor; + +    if (Ctor->isMoveConstructor()) +      return oc_implicit_move_constructor; + +    assert(Ctor->isCopyConstructor() && +           "unexpected sort of implicit constructor"); +    return oc_implicit_copy_constructor;    }    if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) { @@ -6433,6 +6475,9 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,      if (!Meth->isImplicit())        return isTemplate ? oc_method_template : oc_method; +    if (Meth->isMoveAssignmentOperator()) +      return oc_implicit_move_assignment; +      assert(Meth->isCopyAssignmentOperator()             && "implicit method is not copy assignment operator?");      return oc_implicit_copy_assignment; @@ -6676,6 +6721,15 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,    unsigned MinParams = Fn->getMinRequiredArguments(); +  // With invalid overloaded operators, it's possible that we think we +  // have an arity mismatch when it fact it looks like we have the +  // right number of arguments, because only overloaded operators have +  // the weird behavior of overloading member and non-member functions. +  // Just don't report anything. +  if (Fn->isInvalidDecl() &&  +      Fn->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) +    return; +    // at least / at most / exactly    unsigned mode, modeCount;    if (NumFormalArgs < MinParams) { @@ -7772,6 +7826,111 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,                                           ULE->isStdAssociatedNamespace());  } +/// Attempt to recover from an ill-formed use of a non-dependent name in a +/// template, where the non-dependent name was declared after the template +/// was defined. This is common in code written for a compilers which do not +/// correctly implement two-stage name lookup. +/// +/// Returns true if a viable candidate was found and a diagnostic was issued. +static bool +DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, +                       const CXXScopeSpec &SS, LookupResult &R, +                       TemplateArgumentListInfo *ExplicitTemplateArgs, +                       Expr **Args, unsigned NumArgs) { +  if (SemaRef.ActiveTemplateInstantiations.empty() || !SS.isEmpty()) +    return false; + +  for (DeclContext *DC = SemaRef.CurContext; DC; DC = DC->getParent()) { +    SemaRef.LookupQualifiedName(R, DC); + +    if (!R.empty()) { +      R.suppressDiagnostics(); + +      if (isa<CXXRecordDecl>(DC)) { +        // Don't diagnose names we find in classes; we get much better +        // diagnostics for these from DiagnoseEmptyLookup. +        R.clear(); +        return false; +      } + +      OverloadCandidateSet Candidates(FnLoc); +      for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) +        AddOverloadedCallCandidate(SemaRef, I.getPair(), +                                   ExplicitTemplateArgs, Args, NumArgs, +                                   Candidates, false); + +      OverloadCandidateSet::iterator Best; +      if (Candidates.BestViableFunction(SemaRef, FnLoc, Best) != OR_Success) +        // No viable functions. Don't bother the user with notes for functions +        // which don't work and shouldn't be found anyway. +        return false; + +      // Find the namespaces where ADL would have looked, and suggest +      // declaring the function there instead. +      Sema::AssociatedNamespaceSet AssociatedNamespaces; +      Sema::AssociatedClassSet AssociatedClasses; +      SemaRef.FindAssociatedClassesAndNamespaces(Args, NumArgs, +                                                 AssociatedNamespaces, +                                                 AssociatedClasses); +      // Never suggest declaring a function within namespace 'std'.  +      Sema::AssociatedNamespaceSet SuggestedNamespaces; +      if (DeclContext *Std = SemaRef.getStdNamespace()) { +        for (Sema::AssociatedNamespaceSet::iterator +               it = AssociatedNamespaces.begin(), +               end = AssociatedNamespaces.end(); it != end; ++it) { +          if (!Std->Encloses(*it)) +            SuggestedNamespaces.insert(*it); +        } +      } else { +        // Lacking the 'std::' namespace, use all of the associated namespaces. +        SuggestedNamespaces = AssociatedNamespaces; +      } + +      SemaRef.Diag(R.getNameLoc(), diag::err_not_found_by_two_phase_lookup) +        << R.getLookupName(); +      if (SuggestedNamespaces.empty()) { +        SemaRef.Diag(Best->Function->getLocation(), +                     diag::note_not_found_by_two_phase_lookup) +          << R.getLookupName() << 0; +      } else if (SuggestedNamespaces.size() == 1) { +        SemaRef.Diag(Best->Function->getLocation(), +                     diag::note_not_found_by_two_phase_lookup) +          << R.getLookupName() << 1 << *SuggestedNamespaces.begin(); +      } else { +        // FIXME: It would be useful to list the associated namespaces here, +        // but the diagnostics infrastructure doesn't provide a way to produce +        // a localized representation of a list of items. +        SemaRef.Diag(Best->Function->getLocation(), +                     diag::note_not_found_by_two_phase_lookup) +          << R.getLookupName() << 2; +      } + +      // Try to recover by calling this function. +      return true; +    } + +    R.clear(); +  } + +  return false; +} + +/// Attempt to recover from ill-formed use of a non-dependent operator in a +/// template, where the non-dependent operator was declared after the template +/// was defined. +/// +/// Returns true if a viable candidate was found and a diagnostic was issued. +static bool +DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op, +                               SourceLocation OpLoc, +                               Expr **Args, unsigned NumArgs) { +  DeclarationName OpName = +    SemaRef.Context.DeclarationNames.getCXXOperatorName(Op); +  LookupResult R(SemaRef, OpName, OpLoc, Sema::LookupOperatorName); +  return DiagnoseTwoPhaseLookup(SemaRef, OpLoc, CXXScopeSpec(), R, +                                /*ExplicitTemplateArgs=*/0, Args, NumArgs); +} +  /// Attempts to recover from a call where no functions were found.  ///  /// Returns true if new candidates were found. @@ -7780,13 +7939,14 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,                        UnresolvedLookupExpr *ULE,                        SourceLocation LParenLoc,                        Expr **Args, unsigned NumArgs, -                      SourceLocation RParenLoc) { +                      SourceLocation RParenLoc, +                      bool EmptyLookup) {    CXXScopeSpec SS;    SS.Adopt(ULE->getQualifierLoc());    TemplateArgumentListInfo TABuffer; -  const TemplateArgumentListInfo *ExplicitTemplateArgs = 0; +  TemplateArgumentListInfo *ExplicitTemplateArgs = 0;    if (ULE->hasExplicitTemplateArgs()) {      ULE->copyTemplateArgumentsInto(TABuffer);      ExplicitTemplateArgs = &TABuffer; @@ -7794,7 +7954,10 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,    LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),                   Sema::LookupOrdinaryName); -  if (SemaRef.DiagnoseEmptyLookup(S, SS, R, Sema::CTC_Expression)) +  if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R, +                              ExplicitTemplateArgs, Args, NumArgs) && +      (!EmptyLookup || +       SemaRef.DiagnoseEmptyLookup(S, SS, R, Sema::CTC_Expression)))      return ExprError();    assert(!R.empty() && "lookup results empty despite recovery"); @@ -7814,7 +7977,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,      return ExprError();    // This shouldn't cause an infinite loop because we're giving it -  // an expression with non-empty lookup results, which should never +  // an expression with viable lookup results, which should never    // end up here.    return SemaRef.ActOnCallExpr(/*Scope*/ 0, NewFn.take(), LParenLoc,                                 MultiExprArg(Args, NumArgs), RParenLoc); @@ -7860,11 +8023,11 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,    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. +  // BuildRecoveryCallExpr diagnoses the error itself, so we just bail +  // out if it fails.    if (CandidateSet.empty())      return BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, Args, NumArgs, -                                 RParenLoc); +                                 RParenLoc, /*EmptyLookup=*/true);    OverloadCandidateSet::iterator Best;    switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) { @@ -7879,12 +8042,21 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,                                   ExecConfig);    } -  case OR_No_Viable_Function: +  case OR_No_Viable_Function: { +    // Try to recover by looking for viable functions which the user might +    // have meant to call. +    ExprResult Recovery = BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, +                                                Args, NumArgs, RParenLoc, +                                                /*EmptyLookup=*/false); +    if (!Recovery.isInvalid()) +      return Recovery; +      Diag(Fn->getSourceRange().getBegin(),           diag::err_ovl_no_viable_function_in_call)        << ULE->getName() << Fn->getSourceRange();      CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);      break; +  }    case OR_Ambiguous:      Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call) @@ -8073,6 +8245,13 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,    }    case OR_No_Viable_Function: +    // This is an erroneous use of an operator which can be overloaded by +    // a non-member function. Check for non-member operators which were +    // defined too late to be candidates. +    if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, Args, NumArgs)) +      // FIXME: Recover by calling the found function. +      return ExprError(); +      // No viable function; fall through to handling this as a      // built-in operator, which will produce an error message for us.      break; @@ -8354,6 +8533,13 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,               << BinaryOperator::getOpcodeStr(Opc)               << Args[0]->getSourceRange() << Args[1]->getSourceRange();        } else { +        // This is an erroneous use of an operator which can be overloaded by +        // a non-member function. Check for non-member operators which were +        // defined too late to be candidates. +        if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, Args, 2)) +          // FIXME: Recover by calling the found function. +          return ExprError(); +          // No viable function; try to create a built-in operation, which will          // produce an error. Then, show the non-viable candidates.          Result = CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); @@ -8772,6 +8958,19 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,    if (CheckFunctionCall(Method, TheCall))      return ExprError(); +  if ((isa<CXXConstructorDecl>(CurContext) ||  +       isa<CXXDestructorDecl>(CurContext)) &&  +      TheCall->getMethodDecl()->isPure()) { +    const CXXMethodDecl *MD = TheCall->getMethodDecl(); + +    if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts())) +      Diag(MemExpr->getLocStart(),  +           diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor) +        << MD->getDeclName() << isa<CXXDestructorDecl>(CurContext) +        << MD->getParent()->getDeclName(); + +      Diag(MD->getLocStart(), diag::note_previous_decl) << MD->getDeclName(); +  }    return MaybeBindToTemporary(TheCall);  } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp index 65cea7a69d61..d7c0a543eede 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp @@ -501,7 +501,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,      = CondExpr->isTypeDependent() || CondExpr->isValueDependent();    unsigned CondWidth      = HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion); -  bool CondIsSigned = CondTypeBeforePromotion->isSignedIntegerType(); +  bool CondIsSigned  +    = CondTypeBeforePromotion->isSignedIntegerOrEnumerationType();    // Accumulate all of the case values in a vector so that we can sort them    // and detect duplicates.  This vector contains the APInt for the case after @@ -723,7 +724,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,      // If switch has default case, then ignore it.      if (!CaseListIsErroneous  && !HasConstantCond && ET) {        const EnumDecl *ED = ET->getDecl(); -      typedef llvm::SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> EnumValsTy; +      typedef llvm::SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> +        EnumValsTy;        EnumValsTy EnumVals;        // Gather all enum values, set their type and sort them, @@ -1252,7 +1254,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,        ExprResult BoundExpr;        if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(UnqAT))          BoundExpr = Owned(IntegerLiteral::Create(Context, CAT->getSize(), -                                                 Context.IntTy, RangeLoc)); +                                                 Context.getPointerDiffType(), +                                                 RangeLoc));        else if (const VariableArrayType *VAT =                 dyn_cast<VariableArrayType>(UnqAT))          BoundExpr = VAT->getSizeExpr(); @@ -1455,7 +1458,10 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {  /// \param E The expression being returned from the function or block, or  /// being thrown.  /// -/// \param AllowFunctionParameter +/// \param AllowFunctionParameter Whether we allow function parameters to +/// be considered NRVO candidates. C++ prohibits this for NRVO itself, but +/// we re-use this logic to determine whether we should try to move as part of +/// a return or throw (which does allow function parameters).  ///  /// \returns The NRVO candidate variable, if the return statement may use the  /// NRVO, or NULL if there is no such candidate. @@ -1525,12 +1531,11 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,      //   parameter of the selected constructor is not an rvalue reference      //   to the object's type (possibly cv-qualified), overload resolution      //   is performed again, considering the object as an lvalue. -    if (Seq.getKind() != InitializationSequence::FailedSequence) { +    if (Seq) {        for (InitializationSequence::step_iterator Step = Seq.step_begin(),             StepEnd = Seq.step_end();             Step != StepEnd; ++Step) { -        if (Step->Kind -            != InitializationSequence::SK_ConstructorInitialization) +        if (Step->Kind != InitializationSequence::SK_ConstructorInitialization)            continue;          CXXConstructorDecl *Constructor @@ -1583,14 +1588,18 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {        if (Result.isInvalid())          return StmtError();        RetValExp = Result.take(); -      CurBlock->ReturnType = RetValExp->getType(); -      if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) { -        // We have to remove a 'const' added to copied-in variable which was -        // part of the implementation spec. and not the actual qualifier for -        // the variable. -        if (CDRE->isConstQualAdded()) -          CurBlock->ReturnType.removeLocalConst(); // FIXME: local??? -      } + +      if (!RetValExp->isTypeDependent()) { +        CurBlock->ReturnType = RetValExp->getType(); +        if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) { +          // We have to remove a 'const' added to copied-in variable which was +          // part of the implementation spec. and not the actual qualifier for +          // the variable. +          if (CDRE->isConstQualAdded()) +            CurBlock->ReturnType.removeLocalConst(); // FIXME: local??? +        } +      } else +        CurBlock->ReturnType = Context.DependentTy;      } else        CurBlock->ReturnType = Context.VoidTy;    } @@ -1607,13 +1616,17 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {    // compatibility to worry about here.    ReturnStmt *Result = 0;    if (CurBlock->ReturnType->isVoidType()) { -    if (RetValExp) { +    if (RetValExp && !RetValExp->isTypeDependent() && +        (!getLangOptions().CPlusPlus || !RetValExp->getType()->isVoidType())) {        Diag(ReturnLoc, diag::err_return_block_has_expr);        RetValExp = 0;      }      Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0);    } else if (!RetValExp) { -    return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr)); +    if (!CurBlock->ReturnType->isDependentType()) +      return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr)); + +    Result = new (Context) ReturnStmt(ReturnLoc, 0, 0);    } else {      const VarDecl *NRVOCandidate = 0; @@ -1652,7 +1665,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {    // If we need to check for the named return value optimization, save the    // return statement in our scope for later processing. -  if (getLangOptions().CPlusPlus && FnRetType->isRecordType() && +  if (getLangOptions().CPlusPlus && FnRetType->isRecordType() &&         !CurContext->isDependentContext())      FunctionScopes.back()->Returns.push_back(Result); @@ -1661,44 +1674,62 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {  StmtResult  Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { +  // Check for unexpanded parameter packs. +  if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp)) +    return StmtError(); +      if (getCurBlock())      return ActOnBlockReturnStmt(ReturnLoc, RetValExp);    QualType FnRetType; +  QualType DeclaredRetType;    if (const FunctionDecl *FD = getCurFunctionDecl()) {      FnRetType = FD->getResultType(); +    DeclaredRetType = FnRetType;      if (FD->hasAttr<NoReturnAttr>() ||          FD->getType()->getAs<FunctionType>()->getNoReturnAttr())        Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)          << getCurFunctionOrMethodDecl()->getDeclName(); -  } else if (ObjCMethodDecl *MD = getCurMethodDecl()) -    FnRetType = MD->getResultType(); -  else // If we don't have a function/method context, bail. +  } else if (ObjCMethodDecl *MD = getCurMethodDecl()) { +    DeclaredRetType = MD->getResultType(); +    if (MD->hasRelatedResultType() && MD->getClassInterface()) { +      // In the implementation of a method with a related return type, the +      // type used to type-check the validity of return statements within the  +      // method body is a pointer to the type of the class being implemented. +      FnRetType = Context.getObjCInterfaceType(MD->getClassInterface()); +      FnRetType = Context.getObjCObjectPointerType(FnRetType); +    } else { +      FnRetType = DeclaredRetType; +    } +  } else // If we don't have a function/method context, bail.      return StmtError();    ReturnStmt *Result = 0;    if (FnRetType->isVoidType()) { -    if (RetValExp && !RetValExp->isTypeDependent()) { -      // C99 6.8.6.4p1 (ext_ since GCC warns) -      unsigned D = diag::ext_return_has_expr; -      if (RetValExp->getType()->isVoidType()) -        D = diag::ext_return_has_void_expr; -      else { -        ExprResult Result = Owned(RetValExp); -        Result = IgnoredValueConversions(Result.take()); -        if (Result.isInvalid()) -          return StmtError(); -        RetValExp = Result.take(); -        RetValExp = ImpCastExprToType(RetValExp, Context.VoidTy, CK_ToVoid).take(); -      } +    if (RetValExp) { +      if (!RetValExp->isTypeDependent()) { +        // C99 6.8.6.4p1 (ext_ since GCC warns) +        unsigned D = diag::ext_return_has_expr; +        if (RetValExp->getType()->isVoidType()) +          D = diag::ext_return_has_void_expr; +        else { +          ExprResult Result = Owned(RetValExp); +          Result = IgnoredValueConversions(Result.take()); +          if (Result.isInvalid()) +            return StmtError(); +          RetValExp = Result.take(); +          RetValExp = ImpCastExprToType(RetValExp, +                                        Context.VoidTy, CK_ToVoid).take(); +        } -      // return (some void expression); is legal in C++. -      if (D != diag::ext_return_has_void_expr || -          !getLangOptions().CPlusPlus) { -        NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); -        Diag(ReturnLoc, D) -          << CurDecl->getDeclName() << isa<ObjCMethodDecl>(CurDecl) -          << RetValExp->getSourceRange(); +        // return (some void expression); is legal in C++. +        if (D != diag::ext_return_has_void_expr || +            !getLangOptions().CPlusPlus) { +          NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); +          Diag(ReturnLoc, D) +            << CurDecl->getDeclName() << isa<ObjCMethodDecl>(CurDecl) +            << RetValExp->getSourceRange(); +        }        }        CheckImplicitConversions(RetValExp, ReturnLoc); @@ -1730,7 +1761,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {        NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);        InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,                                                                       FnRetType, -                                                                     NRVOCandidate != 0); +                                                            NRVOCandidate != 0);        ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,                                                         FnRetType, RetValExp);        if (Res.isInvalid()) { @@ -1744,6 +1775,17 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {      }      if (RetValExp) { +      // If we type-checked an Objective-C method's return type based +      // on a related return type, we may need to adjust the return +      // type again. Do so now. +      if (DeclaredRetType != FnRetType) { +        ExprResult result = PerformImplicitConversion(RetValExp, +                                                      DeclaredRetType, +                                                      AA_Returning); +        if (result.isInvalid()) return StmtError(); +        RetValExp = result.take(); +      } +        CheckImplicitConversions(RetValExp, ReturnLoc);        RetValExp = MaybeCreateExprWithCleanups(RetValExp);      } @@ -2015,7 +2057,9 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple,      if (InputDomain == AD_Int && OutputDomain == AD_Int &&          !isOperandMentioned(InputOpNo, Pieces) &&          InputExpr->isEvaluatable(Context)) { -      InputExpr = ImpCastExprToType(InputExpr, OutTy, CK_IntegralCast).take(); +      CastKind castKind = +        (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast); +      InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take();        Exprs[InputOpNo] = InputExpr;        NS->setInputExpr(i, InputExpr);        continue; @@ -2251,7 +2295,9 @@ Sema::ActOnSEHExceptBlock(SourceLocation Loc,    assert(FilterExpr && Block);    if(!FilterExpr->getType()->isIntegerType()) { -    return StmtError(Diag(FilterExpr->getExprLoc(), diag::err_filter_expression_integral) << FilterExpr->getType()); +    return StmtError(Diag(FilterExpr->getExprLoc(), +                     diag::err_filter_expression_integral) +                     << FilterExpr->getType());    }    return Owned(SEHExceptStmt::Create(Context,Loc,FilterExpr,Block)); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp index ef0912485b66..5d4caacd8124 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp @@ -92,11 +92,9 @@ void Sema::FilterAcceptableTemplateNames(LookupResult &R) {        //   ambiguity in certain cases (for example, if it is found in more than        //   one base class). If all of the injected-class-names that are found        //   refer to specializations of the same class template, and if the name -      //   is followed by a template-argument-list, the reference refers to the -      //   class template itself and not a specialization thereof, and is not +      //   is used as a template-name, the reference refers to the class +      //   template itself and not a specialization thereof, and is not        //   ambiguous. -      // -      // FIXME: Will we eventually have to do the same for alias templates?        if (ClassTemplateDecl *ClassTmpl = dyn_cast<ClassTemplateDecl>(Repl))          if (!ClassTemplates.insert(ClassTmpl)) {            filter.erase(); @@ -199,7 +197,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S,        // We'll do this lookup again later.        R.suppressDiagnostics();      } else { -      assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD)); +      assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) || +             isa<TypeAliasTemplateDecl>(TD));        TemplateKind = TNK_Type_template;      }    } @@ -603,8 +602,10 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {        T->isPointerType() ||        //   -- reference to object or reference to function,        T->isReferenceType() || -      //   -- pointer to member. +      //   -- pointer to member,        T->isMemberPointerType() || +      //   -- std::nullptr_t. +      T->isNullPtrType() ||        // If T is a dependent type, we can't do the check now, so we        // assume that it is well-formed.        T->isDependentType()) @@ -919,7 +920,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,      //   the class-key shall agree in kind with the original class      //   template declaration (7.1.5.3).      RecordDecl *PrevRecordDecl = PrevClassTemplate->getTemplatedDecl(); -    if (!isAcceptableTagRedeclaration(PrevRecordDecl, Kind, KWLoc, *Name)) { +    if (!isAcceptableTagRedeclaration(PrevRecordDecl, Kind, +                                      TUK == TUK_Definition,  KWLoc, *Name)) {        Diag(KWLoc, diag::err_use_with_wrong_tag)          << Name          << FixItHint::CreateReplacement(KWLoc, PrevRecordDecl->getKindName()); @@ -1062,6 +1064,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S,                                              SourceRange DefArgRange) {    switch (TPC) {    case Sema::TPC_ClassTemplate: +  case Sema::TPC_TypeAliasTemplate:      return false;    case Sema::TPC_FunctionTemplate: @@ -1187,9 +1190,10 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,      bool MissingDefaultArg = false;      // C++0x [temp.param]p11: -    //   If a template parameter of a primary class template is a template -    //   parameter pack, it shall be the last template parameter. -    if (SawParameterPack && TPC == TPC_ClassTemplate) { +    //   If a template parameter of a primary class template or alias template +    //   is a template parameter pack, it shall be the last template parameter. +    if (SawParameterPack && +        (TPC == TPC_ClassTemplate || TPC == TPC_TypeAliasTemplate)) {        Diag(ParameterPackLoc,             diag::err_template_param_pack_must_be_last_template_parameter);        Invalid = true; @@ -1429,19 +1433,41 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {      }      return super::VisitDeclRefExpr(E);    } +   +  bool TraverseInjectedClassNameType(const InjectedClassNameType *T) { +    return TraverseType(T->getInjectedSpecializationType()); +  }  };  } -/// Determines whether a template-id depends on the given parameter +/// Determines whether a given type depends on the given parameter  /// list.  static bool -DependsOnTemplateParameters(const TemplateSpecializationType *TemplateId, -                            TemplateParameterList *Params) { +DependsOnTemplateParameters(QualType T, TemplateParameterList *Params) {    DependencyChecker Checker(Params); -  Checker.TraverseType(QualType(TemplateId, 0)); +  Checker.TraverseType(T);    return Checker.Match;  } +// Find the source range corresponding to the named type in the given +// nested-name-specifier, if any. +static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context, +                                                       QualType T, +                                                       const CXXScopeSpec &SS) { +  NestedNameSpecifierLoc NNSLoc(SS.getScopeRep(), SS.location_data()); +  while (NestedNameSpecifier *NNS = NNSLoc.getNestedNameSpecifier()) { +    if (const Type *CurType = NNS->getAsType()) { +      if (Context.hasSameUnqualifiedType(T, QualType(CurType, 0))) +        return NNSLoc.getTypeLoc().getSourceRange(); +    } else +      break; +     +    NNSLoc = NNSLoc.getPrefix(); +  } +   +  return SourceRange(); +} +  /// \brief Match the given template parameter lists to the given scope  /// specifier, returning the template parameter list that applies to the  /// name. @@ -1449,6 +1475,8 @@ DependsOnTemplateParameters(const TemplateSpecializationType *TemplateId,  /// \param DeclStartLoc the start of the declaration that has a scope  /// specifier or a template parameter list.  /// +/// \param DeclLoc The location of the declaration itself. +///  /// \param SS the scope specifier that will be matched to the given template  /// parameter lists. This scope specifier precedes a qualified name that is  /// being declared. @@ -1473,6 +1501,7 @@ DependsOnTemplateParameters(const TemplateSpecializationType *TemplateId,  /// itself a template).  TemplateParameterList *  Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, +                                              SourceLocation DeclLoc,                                                const CXXScopeSpec &SS,                                            TemplateParameterList **ParamLists,                                                unsigned NumParamLists, @@ -1480,138 +1509,268 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,                                                bool &IsExplicitSpecialization,                                                bool &Invalid) {    IsExplicitSpecialization = false; - -  // Find the template-ids that occur within the nested-name-specifier. These -  // template-ids will match up with the template parameter lists. -  llvm::SmallVector<const TemplateSpecializationType *, 4> -    TemplateIdsInSpecifier; -  llvm::SmallVector<ClassTemplateSpecializationDecl *, 4> -    ExplicitSpecializationsInSpecifier; -  for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep(); -       NNS; NNS = NNS->getPrefix()) { -    const Type *T = NNS->getAsType(); -    if (!T) break; - -    // C++0x [temp.expl.spec]p17: -    //   A member or a member template may be nested within many -    //   enclosing class templates. In an explicit specialization for -    //   such a member, the member declaration shall be preceded by a -    //   template<> for each enclosing class template that is -    //   explicitly specialized. -    // -    // Following the existing practice of GNU and EDG, we allow a typedef of a -    // template specialization type. -    while (const TypedefType *TT = dyn_cast<TypedefType>(T)) -      T = TT->getDecl()->getUnderlyingType().getTypePtr(); - -    if (const TemplateSpecializationType *SpecType -                                  = dyn_cast<TemplateSpecializationType>(T)) { -      TemplateDecl *Template = SpecType->getTemplateName().getAsTemplateDecl(); -      if (!Template) -        continue; // FIXME: should this be an error? probably... - -      if (const RecordType *Record = SpecType->getAs<RecordType>()) { -        ClassTemplateSpecializationDecl *SpecDecl -          = cast<ClassTemplateSpecializationDecl>(Record->getDecl()); -        // If the nested name specifier refers to an explicit specialization, -        // we don't need a template<> header. -        if (SpecDecl->getSpecializationKind() == TSK_ExplicitSpecialization) { -          ExplicitSpecializationsInSpecifier.push_back(SpecDecl); -          continue; +  Invalid = false; +   +  // The sequence of nested types to which we will match up the template +  // parameter lists. We first build this list by starting with the type named +  // by the nested-name-specifier and walking out until we run out of types. +  llvm::SmallVector<QualType, 4> NestedTypes; +  QualType T; +  if (SS.getScopeRep()) { +    if (CXXRecordDecl *Record  +              = dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, true))) +      T = Context.getTypeDeclType(Record); +    else +      T = QualType(SS.getScopeRep()->getAsType(), 0); +  } +   +  // If we found an explicit specialization that prevents us from needing +  // 'template<>' headers, this will be set to the location of that +  // explicit specialization. +  SourceLocation ExplicitSpecLoc; +   +  while (!T.isNull()) { +    NestedTypes.push_back(T); +     +    // Retrieve the parent of a record type. +    if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) { +      // If this type is an explicit specialization, we're done. +      if (ClassTemplateSpecializationDecl *Spec +          = dyn_cast<ClassTemplateSpecializationDecl>(Record)) { +        if (!isa<ClassTemplatePartialSpecializationDecl>(Spec) &&  +            Spec->getSpecializationKind() == TSK_ExplicitSpecialization) { +          ExplicitSpecLoc = Spec->getLocation(); +          break;          } +      } else if (Record->getTemplateSpecializationKind() +                                                == TSK_ExplicitSpecialization) { +        ExplicitSpecLoc = Record->getLocation(); +        break; +      } +       +      if (TypeDecl *Parent = dyn_cast<TypeDecl>(Record->getParent())) +        T = Context.getTypeDeclType(Parent); +      else +        T = QualType(); +      continue; +    }  +     +    if (const TemplateSpecializationType *TST +                                     = T->getAs<TemplateSpecializationType>()) { +      if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) { +        if (TypeDecl *Parent = dyn_cast<TypeDecl>(Template->getDeclContext())) +          T = Context.getTypeDeclType(Parent); +        else +          T = QualType(); +        continue;                } - -      TemplateIdsInSpecifier.push_back(SpecType);      } -  } - -  // Reverse the list of template-ids in the scope specifier, so that we can -  // more easily match up the template-ids and the template parameter lists. -  std::reverse(TemplateIdsInSpecifier.begin(), TemplateIdsInSpecifier.end()); - -  SourceLocation FirstTemplateLoc = DeclStartLoc; -  if (NumParamLists) -    FirstTemplateLoc = ParamLists[0]->getTemplateLoc(); - -  // Match the template-ids found in the specifier to the template parameter -  // lists. -  unsigned ParamIdx = 0, TemplateIdx = 0; -  for (unsigned NumTemplateIds = TemplateIdsInSpecifier.size(); -       TemplateIdx != NumTemplateIds; ++TemplateIdx) { -    const TemplateSpecializationType *TemplateId -      = TemplateIdsInSpecifier[TemplateIdx]; -    bool DependentTemplateId = TemplateId->isDependentType(); - -    // In friend declarations we can have template-ids which don't -    // depend on the corresponding template parameter lists.  But -    // assume that empty parameter lists are supposed to match this -    // template-id. -    if (IsFriend && ParamIdx < NumParamLists && ParamLists[ParamIdx]->size()) { -      if (!DependentTemplateId || -          !DependsOnTemplateParameters(TemplateId, ParamLists[ParamIdx])) -        continue; +     +    // Look one step prior in a dependent template specialization type. +    if (const DependentTemplateSpecializationType *DependentTST +                          = T->getAs<DependentTemplateSpecializationType>()) { +      if (NestedNameSpecifier *NNS = DependentTST->getQualifier()) +        T = QualType(NNS->getAsType(), 0); +      else +        T = QualType(); +      continue; +    } +     +    // Look one step prior in a dependent name type. +    if (const DependentNameType *DependentName = T->getAs<DependentNameType>()){ +      if (NestedNameSpecifier *NNS = DependentName->getQualifier()) +        T = QualType(NNS->getAsType(), 0); +      else +        T = QualType(); +      continue; +    } +     +    // Retrieve the parent of an enumeration type. +    if (const EnumType *EnumT = T->getAs<EnumType>()) { +      // FIXME: Forward-declared enums require a TSK_ExplicitSpecialization +      // check here. +      EnumDecl *Enum = EnumT->getDecl(); +       +      // Get to the parent type. +      if (TypeDecl *Parent = dyn_cast<TypeDecl>(Enum->getParent())) +        T = Context.getTypeDeclType(Parent); +      else +        T = QualType();       +      continue;      } -    if (ParamIdx >= NumParamLists) { -      // We have a template-id without a corresponding template parameter -      // list. +    T = QualType(); +  } +  // Reverse the nested types list, since we want to traverse from the outermost +  // to the innermost while checking template-parameter-lists. +  std::reverse(NestedTypes.begin(), NestedTypes.end()); + +  // C++0x [temp.expl.spec]p17: +  //   A member or a member template may be nested within many +  //   enclosing class templates. In an explicit specialization for +  //   such a member, the member declaration shall be preceded by a +  //   template<> for each enclosing class template that is +  //   explicitly specialized. +  bool SawNonEmptyTemplateParameterList = false; +  unsigned ParamIdx = 0; +  for (unsigned TypeIdx = 0, NumTypes = NestedTypes.size(); TypeIdx != NumTypes; +       ++TypeIdx) { +    T = NestedTypes[TypeIdx]; +     +    // Whether we expect a 'template<>' header. +    bool NeedEmptyTemplateHeader = false; -      // ...which is fine if this is a friend declaration. -      if (IsFriend) { -        IsExplicitSpecialization = true; -        break; +    // Whether we expect a template header with parameters. +    bool NeedNonemptyTemplateHeader = false; +     +    // For a dependent type, the set of template parameters that we +    // expect to see. +    TemplateParameterList *ExpectedTemplateParams = 0; + +    // C++0x [temp.expl.spec]p15: +    //   A member or a member template may be nested within many enclosing  +    //   class templates. In an explicit specialization for such a member, the  +    //   member declaration shall be preceded by a template<> for each  +    //   enclosing class template that is explicitly specialized. +    if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) { +      if (ClassTemplatePartialSpecializationDecl *Partial +            = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) { +        ExpectedTemplateParams = Partial->getTemplateParameters(); +        NeedNonemptyTemplateHeader = true; +      } else if (Record->isDependentType()) { +        if (Record->getDescribedClassTemplate()) { +          ExpectedTemplateParams = Record->getDescribedClassTemplate() +                                                      ->getTemplateParameters(); +          NeedNonemptyTemplateHeader = true; +        } +      } else if (ClassTemplateSpecializationDecl *Spec +                     = dyn_cast<ClassTemplateSpecializationDecl>(Record)) { +        // C++0x [temp.expl.spec]p4: +        //   Members of an explicitly specialized class template are defined +        //   in the same manner as members of normal classes, and not using  +        //   the template<> syntax.  +        if (Spec->getSpecializationKind() != TSK_ExplicitSpecialization) +          NeedEmptyTemplateHeader = true; +        else +          continue; +      } else if (Record->getTemplateSpecializationKind()) { +        if (Record->getTemplateSpecializationKind()  +                                                != TSK_ExplicitSpecialization && +            TypeIdx == NumTypes - 1) +          IsExplicitSpecialization = true; +         +        continue;        } - -      if (DependentTemplateId) { -        // FIXME: the location information here isn't great. -        Diag(SS.getRange().getBegin(), -             diag::err_template_spec_needs_template_parameters) -          << QualType(TemplateId, 0) -          << SS.getRange(); -        Invalid = true; -      } else { -        Diag(SS.getRange().getBegin(), diag::err_template_spec_needs_header) -          << SS.getRange() -          << FixItHint::CreateInsertion(FirstTemplateLoc, "template<> "); -        IsExplicitSpecialization = true; +    } else if (const TemplateSpecializationType *TST +                                     = T->getAs<TemplateSpecializationType>()) { +      if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {         +        ExpectedTemplateParams = Template->getTemplateParameters(); +        NeedNonemptyTemplateHeader = true;                } -      return 0; +    } else if (T->getAs<DependentTemplateSpecializationType>()) { +      // FIXME:  We actually could/should check the template arguments here +      // against the corresponding template parameter list. +      NeedNonemptyTemplateHeader = false; +    }  +     +    // C++ [temp.expl.spec]p16: +    //   In an explicit specialization declaration for a member of a class  +    //   template or a member template that ap- pears in namespace scope, the  +    //   member template and some of its enclosing class templates may remain  +    //   unspecialized, except that the declaration shall not explicitly  +    //   specialize a class member template if its en- closing class templates  +    //   are not explicitly specialized as well. +    if (ParamIdx < NumParamLists) { +      if (ParamLists[ParamIdx]->size() == 0) { +        if (SawNonEmptyTemplateParameterList) { +          Diag(DeclLoc, diag::err_specialize_member_of_template) +            << ParamLists[ParamIdx]->getSourceRange(); +          Invalid = true; +          IsExplicitSpecialization = false; +          return 0; +        } +      } else +        SawNonEmptyTemplateParameterList = true;      } - -    // Check the template parameter list against its corresponding template-id. -    if (DependentTemplateId) { -      TemplateParameterList *ExpectedTemplateParams = 0; - -      // Are there cases in (e.g.) friends where this won't match? -      if (const InjectedClassNameType *Injected -            = TemplateId->getAs<InjectedClassNameType>()) { -        CXXRecordDecl *Record = Injected->getDecl(); -        if (ClassTemplatePartialSpecializationDecl *Partial = -              dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) -          ExpectedTemplateParams = Partial->getTemplateParameters(); +     +    if (NeedEmptyTemplateHeader) { +      // If we're on the last of the types, and we need a 'template<>' header +      // here, then it's an explicit specialization. +      if (TypeIdx == NumTypes - 1) +        IsExplicitSpecialization = true; +       +      if (ParamIdx < NumParamLists) { +        if (ParamLists[ParamIdx]->size() > 0) { +          // The header has template parameters when it shouldn't. Complain. +          Diag(ParamLists[ParamIdx]->getTemplateLoc(),  +               diag::err_template_param_list_matches_nontemplate) +            << T +            << SourceRange(ParamLists[ParamIdx]->getLAngleLoc(), +                           ParamLists[ParamIdx]->getRAngleLoc()) +            << getRangeOfTypeInNestedNameSpecifier(Context, T, SS); +          Invalid = true; +          return 0; +        } +         +        // Consume this template header. +        ++ParamIdx; +        continue; +      }  +       +      if (!IsFriend) { +        // We don't have a template header, but we should. +        SourceLocation ExpectedTemplateLoc; +        if (NumParamLists > 0) +          ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();          else -          ExpectedTemplateParams = Record->getDescribedClassTemplate() -            ->getTemplateParameters(); -      } +          ExpectedTemplateLoc = DeclStartLoc; -      if (ExpectedTemplateParams) -        TemplateParameterListsAreEqual(ParamLists[ParamIdx], -                                       ExpectedTemplateParams, -                                       true, TPL_TemplateMatch); - -      CheckTemplateParameterList(ParamLists[ParamIdx], 0, -                                 TPC_ClassTemplateMember); -    } else if (ParamLists[ParamIdx]->size() > 0) -      Diag(ParamLists[ParamIdx]->getTemplateLoc(), -           diag::err_template_param_list_matches_nontemplate) -        << TemplateId -        << ParamLists[ParamIdx]->getSourceRange(); -    else -      IsExplicitSpecialization = true; +        Diag(DeclLoc, diag::err_template_spec_needs_header) +          << getRangeOfTypeInNestedNameSpecifier(Context, T, SS) +          << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> "); +      } +       +      continue; +    } +     +    if (NeedNonemptyTemplateHeader) { +      // In friend declarations we can have template-ids which don't +      // depend on the corresponding template parameter lists.  But +      // assume that empty parameter lists are supposed to match this +      // template-id. +      if (IsFriend && T->isDependentType()) { +        if (ParamIdx < NumParamLists && +            DependsOnTemplateParameters(T, ParamLists[ParamIdx])) +          ExpectedTemplateParams = 0; +        else  +          continue; +      } -    ++ParamIdx; +      if (ParamIdx < NumParamLists) { +        // Check the template parameter list, if we can.         +        if (ExpectedTemplateParams && +            !TemplateParameterListsAreEqual(ParamLists[ParamIdx], +                                            ExpectedTemplateParams, +                                            true, TPL_TemplateMatch)) +          Invalid = true; +         +        if (!Invalid && +            CheckTemplateParameterList(ParamLists[ParamIdx], 0, +                                       TPC_ClassTemplateMember)) +          Invalid = true; +         +        ++ParamIdx; +        continue; +      } +       +      Diag(DeclLoc, diag::err_template_spec_needs_template_parameters) +        << T +        << getRangeOfTypeInNestedNameSpecifier(Context, T, SS); +      Invalid = true; +      continue; +    }    } - +        // If there were at least as many template-ids as there were template    // parameter lists, then there are no template parameter lists remaining for    // the declaration itself. @@ -1619,32 +1778,53 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,      return 0;    // If there were too many template parameter lists, complain about that now. -  if (ParamIdx != NumParamLists - 1) { -    while (ParamIdx < NumParamLists - 1) { -      bool isExplicitSpecHeader = ParamLists[ParamIdx]->size() == 0; -      Diag(ParamLists[ParamIdx]->getTemplateLoc(), -           isExplicitSpecHeader? diag::warn_template_spec_extra_headers -                               : diag::err_template_spec_extra_headers) -        << SourceRange(ParamLists[ParamIdx]->getTemplateLoc(), -                       ParamLists[ParamIdx]->getRAngleLoc()); - -      if (isExplicitSpecHeader && !ExplicitSpecializationsInSpecifier.empty()) { -        Diag(ExplicitSpecializationsInSpecifier.back()->getLocation(), -             diag::note_explicit_template_spec_does_not_need_header) -          << ExplicitSpecializationsInSpecifier.back(); -        ExplicitSpecializationsInSpecifier.pop_back(); -      } - -      // We have a template parameter list with no corresponding scope, which -      // means that the resulting template declaration can't be instantiated -      // properly (we'll end up with dependent nodes when we shouldn't). -      if (!isExplicitSpecHeader) -        Invalid = true; - -      ++ParamIdx; +  if (ParamIdx < NumParamLists - 1) { +    bool HasAnyExplicitSpecHeader = false; +    bool AllExplicitSpecHeaders = true; +    for (unsigned I = ParamIdx; I != NumParamLists - 1; ++I) { +      if (ParamLists[I]->size() == 0) +        HasAnyExplicitSpecHeader = true; +      else +        AllExplicitSpecHeaders = false;      } +     +    Diag(ParamLists[ParamIdx]->getTemplateLoc(), +         AllExplicitSpecHeaders? diag::warn_template_spec_extra_headers +                               : diag::err_template_spec_extra_headers) +      << SourceRange(ParamLists[ParamIdx]->getTemplateLoc(), +                     ParamLists[NumParamLists - 2]->getRAngleLoc()); + +    // If there was a specialization somewhere, such that 'template<>' is +    // not required, and there were any 'template<>' headers, note where the +    // specialization occurred. +    if (ExplicitSpecLoc.isValid() && HasAnyExplicitSpecHeader) +      Diag(ExplicitSpecLoc,  +           diag::note_explicit_template_spec_does_not_need_header) +        << NestedTypes.back(); +     +    // We have a template parameter list with no corresponding scope, which +    // means that the resulting template declaration can't be instantiated +    // properly (we'll end up with dependent nodes when we shouldn't). +    if (!AllExplicitSpecHeaders) +      Invalid = true;    } +  // C++ [temp.expl.spec]p16: +  //   In an explicit specialization declaration for a member of a class  +  //   template or a member template that ap- pears in namespace scope, the  +  //   member template and some of its enclosing class templates may remain  +  //   unspecialized, except that the declaration shall not explicitly  +  //   specialize a class member template if its en- closing class templates  +  //   are not explicitly specialized as well. +  if (ParamLists[NumParamLists - 1]->size() == 0 &&  +      SawNonEmptyTemplateParameterList) { +    Diag(DeclLoc, diag::err_specialize_member_of_template) +      << ParamLists[ParamIdx]->getSourceRange(); +    Invalid = true; +    IsExplicitSpecialization = false; +    return 0; +  } +      // Return the last template parameter list, which corresponds to the    // entity being declared.    return ParamLists[NumParamLists - 1]; @@ -1655,7 +1835,8 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) {      Diag(Template->getLocation(), diag::note_template_declared_here)        << (isa<FunctionTemplateDecl>(Template)? 0            : isa<ClassTemplateDecl>(Template)? 1 -          : 2) +          : isa<TypeAliasTemplateDecl>(Template)? 2 +          : 3)        << Template->getDeclName();      return;    } @@ -1675,13 +1856,24 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) {  QualType Sema::CheckTemplateIdType(TemplateName Name,                                     SourceLocation TemplateLoc,                                     TemplateArgumentListInfo &TemplateArgs) { +  DependentTemplateName *DTN = Name.getAsDependentTemplateName(); +  if (DTN && DTN->isIdentifier()) +    // When building a template-id where the template-name is dependent, +    // assume the template is a type template. Either our assumption is +    // correct, or the code is ill-formed and will be diagnosed when the +    // dependent name is substituted. +    return Context.getDependentTemplateSpecializationType(ETK_None, +                                                          DTN->getQualifier(), +                                                          DTN->getIdentifier(), +                                                          TemplateArgs); +    TemplateDecl *Template = Name.getAsTemplateDecl();    if (!Template || isa<FunctionTemplateDecl>(Template)) {      // We might have a substituted template template parameter pack. If so,      // build a template specialization type for it.      if (Name.getAsSubstTemplateTemplateParmPack())        return Context.getTemplateSpecializationType(Name, TemplateArgs); -     +      Diag(TemplateLoc, diag::err_template_id_not_a_type)        << Name;      NoteAllFoundTemplates(Name); @@ -1700,9 +1892,32 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,    QualType CanonType; -  if (Name.isDependent() || -      TemplateSpecializationType::anyDependentTemplateArguments( -                                                      TemplateArgs)) { +  if (TypeAliasTemplateDecl *AliasTemplate +        = dyn_cast<TypeAliasTemplateDecl>(Template)) { +    // Find the canonical type for this type alias template specialization. +    TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl(); +    if (Pattern->isInvalidDecl()) +      return QualType(); + +    TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, +                                      Converted.data(), Converted.size()); + +    // Only substitute for the innermost template argument list. +    MultiLevelTemplateArgumentList TemplateArgLists; +    TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); +    unsigned Depth = AliasTemplate->getTemplateParameters()->getDepth(); +    for (unsigned I = 0; I < Depth; ++I) +      TemplateArgLists.addOuterTemplateArguments(0, 0); + +    InstantiatingTemplate Inst(*this, TemplateLoc, Template); +    CanonType = SubstType(Pattern->getUnderlyingType(), +                          TemplateArgLists, AliasTemplate->getLocation(), +                          AliasTemplate->getDeclName()); +    if (CanonType.isNull()) +      return QualType(); +  } else if (Name.isDependent() || +             TemplateSpecializationType::anyDependentTemplateArguments( +               TemplateArgs)) {      // This class template specialization is a dependent      // type. Therefore, its canonical type is another class template      // specialization type that contains all of the converted @@ -1894,6 +2109,16 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,        SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());      return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));    } + +  if (TypeAliasTemplateDecl *TAT = +        dyn_cast_or_null<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) { +    // C++0x [dcl.type.elab]p2: +    //   If the identifier resolves to a typedef-name or the simple-template-id +    //   resolves to an alias template specialization, the +    //   elaborated-type-specifier is ill-formed. +    Diag(TemplateLoc, diag::err_tag_reference_non_tag) << 4; +    Diag(TAT->getLocation(), diag::note_declared_at); +  }    QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);    if (Result.isNull()) @@ -1906,7 +2131,8 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,      IdentifierInfo *Id = D->getIdentifier();      assert(Id && "templated class must have an identifier"); -    if (!isAcceptableTagRedeclaration(D, TagKind, TagLoc, *Id)) { +    if (!isAcceptableTagRedeclaration(D, TagKind, TUK == TUK_Definition, +                                      TagLoc, *Id)) {        Diag(TagLoc, diag::err_use_with_wrong_tag)          << Result          << FixItHint::CreateReplacement(SourceRange(TagLoc), D->getKindName()); @@ -2485,7 +2711,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,        }        // We have a template argument that actually does refer to a class -      // template, template alias, or template template parameter, and +      // template, alias template, or template template parameter, and        // therefore cannot be a non-type template argument.        Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr)          << Arg.getSourceRange(); @@ -2562,7 +2788,8 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,    case TemplateArgument::Type:      // We have a template template parameter but the template      // argument does not refer to a template. -    Diag(Arg.getLocation(), diag::err_template_arg_must_be_template); +    Diag(Arg.getLocation(), diag::err_template_arg_must_be_template) +      << getLangOptions().CPlusPlus0x;      return true;    case TemplateArgument::Declaration: @@ -2631,9 +2858,6 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,    unsigned ArgIdx = 0;    LocalInstantiationScope InstScope(*this, true);    while (Param != ParamEnd) { -    if (ArgIdx > NumArgs && PartialTemplateArgs) -      break; -      if (ArgIdx < NumArgs) {        // If we have an expanded parameter pack, make sure we don't have too        // many arguments. @@ -2674,11 +2898,31 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,        continue;      } +    // If we're checking a partial template argument list, we're done. +    if (PartialTemplateArgs) { +      if ((*Param)->isTemplateParameterPack() && !ArgumentPack.empty()) +        Converted.push_back(TemplateArgument::CreatePackCopy(Context, +                                                         ArgumentPack.data(), +                                                         ArgumentPack.size())); +         +      return Invalid; +    } +      // If we have a template parameter pack with no more corresponding      // arguments, just break out now and we'll fill in the argument pack below.      if ((*Param)->isTemplateParameterPack())        break; +    // If our template is a template template parameter that hasn't acquired +    // its proper context yet (e.g., because we're using the template template +    // parameter in the signature of a function template, before we've built +    // the function template itself), don't attempt substitution of default +    // template arguments at this point: we don't have enough context to +    // do it properly. +    if (isTemplateTemplateParameter &&  +        Template->getDeclContext()->isTranslationUnit()) +      break; +          // We have a default template argument that we will use.      TemplateArgumentLoc Arg; @@ -2689,7 +2933,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,      // the default argument.      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {        if (!TTP->hasDefaultArgument()) { -        assert((Invalid || PartialTemplateArgs) && "Missing default argument"); +        assert(Invalid && "Missing default argument");          break;        } @@ -2707,7 +2951,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,      } else if (NonTypeTemplateParmDecl *NTTP                   = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {        if (!NTTP->hasDefaultArgument()) { -        assert((Invalid || PartialTemplateArgs) && "Missing default argument"); +        assert(Invalid && "Missing default argument");          break;        } @@ -2726,7 +2970,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,          = cast<TemplateTemplateParmDecl>(*Param);        if (!TempParm->hasDefaultArgument()) { -        assert((Invalid || PartialTemplateArgs) && "Missing default argument"); +        assert(Invalid && "Missing default argument");          break;        } @@ -2772,9 +3016,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,      // in arguments for non-template parameter packs.      if ((*Param)->isTemplateParameterPack()) { -      if (PartialTemplateArgs && ArgumentPack.empty()) { -        Converted.push_back(TemplateArgument()); -      } else if (ArgumentPack.empty()) +      if (ArgumentPack.empty())          Converted.push_back(TemplateArgument(0, 0));        else {          Converted.push_back(TemplateArgument::CreatePackCopy(Context, @@ -2918,6 +3160,11 @@ bool UnnamedLocalNoLinkageFinder::VisitDecltypeType(const DecltypeType*) {    return false;  } +bool UnnamedLocalNoLinkageFinder::VisitUnaryTransformType( +                                                    const UnaryTransformType*) { +  return false; +} +  bool UnnamedLocalNoLinkageFinder::VisitAutoType(const AutoType *T) {    return Visit(T->getDeducedType());  } @@ -3501,32 +3748,49 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,        return ExprError();      } +    // Add the value of this argument to the list of converted +    // arguments. We use the bitwidth and signedness of the template +    // parameter. +    if (Arg->isValueDependent()) { +      // The argument is value-dependent. Create a new +      // TemplateArgument with the converted expression. +      Converted = TemplateArgument(Arg); +      return Owned(Arg); +    } +      QualType IntegerType = Context.getCanonicalType(ParamType);      if (const EnumType *Enum = IntegerType->getAs<EnumType>())        IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType()); -    if (!Arg->isValueDependent()) { +    if (ParamType->isBooleanType()) { +      // Value must be zero or one. +      Value = Value != 0; +      unsigned AllowedBits = Context.getTypeSize(IntegerType); +      if (Value.getBitWidth() != AllowedBits) +        Value = Value.extOrTrunc(AllowedBits); +      Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType()); +    } else {        llvm::APSInt OldValue = Value; - +              // Coerce the template argument's value to the value it will have        // based on the template parameter's type.        unsigned AllowedBits = Context.getTypeSize(IntegerType);        if (Value.getBitWidth() != AllowedBits)          Value = Value.extOrTrunc(AllowedBits); -      Value.setIsSigned(IntegerType->isSignedIntegerType()); - +      Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType()); +              // Complain if an unsigned parameter received a negative value. -      if (IntegerType->isUnsignedIntegerType() -          && (OldValue.isSigned() && OldValue.isNegative())) { +      if (IntegerType->isUnsignedIntegerOrEnumerationType() +               && (OldValue.isSigned() && OldValue.isNegative())) {          Diag(Arg->getSourceRange().getBegin(), diag::warn_template_arg_negative)            << OldValue.toString(10) << Value.toString(10) << Param->getType()            << Arg->getSourceRange();          Diag(Param->getLocation(), diag::note_template_param_here);        } - +              // Complain if we overflowed the template parameter's type.        unsigned RequiredBits; -      if (IntegerType->isUnsignedIntegerType()) +      if (IntegerType->isUnsignedIntegerOrEnumerationType())          RequiredBits = OldValue.getActiveBits();        else if (OldValue.isUnsigned())          RequiredBits = OldValue.getActiveBits() + 1; @@ -3541,16 +3805,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,        }      } -    // Add the value of this argument to the list of converted -    // arguments. We use the bitwidth and signedness of the template -    // parameter. -    if (Arg->isValueDependent()) { -      // The argument is value-dependent. Create a new -      // TemplateArgument with the converted expression. -      Converted = TemplateArgument(Arg); -      return Owned(Arg); -    } -      Converted = TemplateArgument(Value,                                   ParamType->isEnumeralType() ? ParamType                                                               : IntegerType); @@ -3563,10 +3817,17 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,    // from a template argument of type std::nullptr_t to a non-type    // template parameter of type pointer to object, pointer to    // function, or pointer-to-member, respectively. -  if (ArgType->isNullPtrType() && -      (ParamType->isPointerType() || ParamType->isMemberPointerType())) { -    Converted = TemplateArgument((NamedDecl *)0); -    return Owned(Arg); +  if (ArgType->isNullPtrType()) { +    if (ParamType->isPointerType() || ParamType->isMemberPointerType()) { +      Converted = TemplateArgument((NamedDecl *)0); +      return Owned(Arg); +    } +     +    if (ParamType->isNullPtrType()) { +      llvm::APSInt Zero(Context.getTypeSize(Context.NullPtrTy), true); +      Converted = TemplateArgument(Zero, Context.NullPtrTy); +      return Owned(Arg); +    }    }    // Handle pointer-to-function, reference-to-function, and @@ -3715,9 +3976,10 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,      return false;    } -  // C++ [temp.arg.template]p1: +  // C++0x [temp.arg.template]p1:    //   A template-argument for a template template-parameter shall be -  //   the name of a class template, expressed as id-expression. Only +  //   the name of a class template or an alias template, expressed as an +  //   id-expression. When the template-argument names a class template, only    //   primary class templates are considered when matching the    //   template template argument with the corresponding parameter;    //   partial specializations are not considered even if their @@ -3727,7 +3989,8 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,    // will happen when we are dealing with, e.g., class template    // partial specializations.    if (!isa<ClassTemplateDecl>(Template) && -      !isa<TemplateTemplateParmDecl>(Template)) { +      !isa<TemplateTemplateParmDecl>(Template) && +      !isa<TypeAliasTemplateDecl>(Template)) {      assert(isa<FunctionTemplateDecl>(Template) &&             "Only function templates are possible here");      Diag(Arg.getLocation(), diag::err_template_arg_not_class_template); @@ -3858,6 +4121,9 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,                                              Arg.getAsIntegral()->getBoolValue(),                                              T, Loc)); +  if (T->isNullPtrType()) +    return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc)); +      // If this is an enum type that we're instantiating, we need to use an integer    // type the same size as the enumerator.  We don't want to build an    // IntegerLiteral with enum type. @@ -4044,7 +4310,7 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,    // C++0x [temp.arg.template]p3:    //   A template-argument matches a template template-parameter (call it P)    //   when each of the template parameters in the template-parameter-list of -  //   the template-argument's corresponding class template or template alias +  //   the template-argument's corresponding class template or alias template    //   (call it A) matches the corresponding template parameter in the    //   template-parameter-list of P. [...]    TemplateParameterList::iterator NewParm = New->begin(); @@ -4442,7 +4708,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,    // friend declarations.    bool Invalid = false;    TemplateParameterList *TemplateParams -    = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, SS, +    = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc,  +                                              TemplateNameLoc, +                                              SS,                          (TemplateParameterList**)TemplateParameterLists.get(),                                                TemplateParameterLists.size(),                                                TUK == TUK_Friend, @@ -4509,7 +4777,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,    TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);    assert(Kind != TTK_Enum && "Invalid enum tag in class template spec!");    if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(), -                                    Kind, KWLoc, +                                    Kind, TUK == TUK_Definition, KWLoc,                                      *ClassTemplate->getIdentifier())) {      Diag(KWLoc, diag::err_use_with_wrong_tag)        << ClassTemplate @@ -5180,7 +5448,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,                                           SpecInfo->getPointOfInstantiation(),                                               HasNoEffect))      return true; - +      // Mark the prior declaration as an explicit specialization, so that later    // clients know that this is an explicit specialization.    if (!isFriend) { @@ -5200,7 +5468,8 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,                                          TemplArgs, /*InsertPos=*/0,                                      SpecInfo->getTemplateSpecializationKind(),                                          TemplArgsAsWritten); - +  FD->setStorageClass(Specialization->getStorageClass()); +      // The "previous declaration" for this function template specialization is    // the prior function template specialization.    Previous.clear(); @@ -5479,7 +5748,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,    assert(Kind != TTK_Enum &&           "Invalid enum tag in class template explicit instantiation!");    if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(), -                                    Kind, KWLoc, +                                    Kind, /*isDefinition*/false, KWLoc,                                      *ClassTemplate->getIdentifier())) {      Diag(KWLoc, diag::err_use_with_wrong_tag)        << ClassTemplate @@ -5801,11 +6070,20 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,    if (R.isNull())      return true; +  // C++ [dcl.stc]p1: +  //   A storage-class-specifier shall not be specified in [...] an explicit  +  //   instantiation (14.7.2) directive.    if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { -    // Cannot explicitly instantiate a typedef.      Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_of_typedef)        << Name;      return true; +  } else if (D.getDeclSpec().getStorageClassSpec()  +                                                != DeclSpec::SCS_unspecified) { +    // Complain about then remove the storage class specifier. +    Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_storage_class) +      << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); +     +    D.getMutableDeclSpec().ClearStorageClassSpecs();    }    // C++0x [temp.explicit]p1: diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp index 235af049cf84..7d0ce8b2e71d 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2314,7 +2314,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,                                FunctionTemplate->getLocation(),                                FunctionTemplate->getSourceRange().getEnd(),                                0, Builder, -                              CTAK_Deduced)) { +                              CTAK_Specified)) {        Info.Param = makeTemplateParameter(                           const_cast<NamedDecl *>(TemplateParams->getParam(I)));        // FIXME: These template arguments are temporary. Free them! @@ -2500,6 +2500,12 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,    if (ParamRefType) {      QualType PointeeType = ParamRefType->getPointeeType(); +    // If the argument has incomplete array type, try to complete it's type. +    if (ArgType->isIncompleteArrayType() && +        !S.RequireCompleteExprType(Arg, S.PDiag(),  +                                   std::make_pair(SourceLocation(), S.PDiag()))) +      ArgType = Arg->getType(); +      //   [C++0x] If P is an rvalue reference to a cv-unqualified      //   template parameter and the argument is an lvalue, the type      //   "lvalue reference to A" is used in place of A for type @@ -2507,7 +2513,9 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,      if (isa<RValueReferenceType>(ParamType)) {        if (!PointeeType.getQualifiers() &&            isa<TemplateTypeParmType>(PointeeType) && -          Arg->Classify(S.Context).isLValue()) +          Arg->Classify(S.Context).isLValue() && +          Arg->getType() != S.Context.OverloadTy && +          Arg->getType() != S.Context.BoundMemberTy)          ArgType = S.Context.getLValueReferenceType(ArgType);      } @@ -3884,6 +3892,13 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,                                   OnlyDeduced, Depth, Used);      break; +  case Type::UnaryTransform: +    if (!OnlyDeduced) +      MarkUsedTemplateParameters(SemaRef, +                               cast<UnaryTransformType>(T)->getUnderlyingType(), +                                 OnlyDeduced, Depth, Used); +    break; +    case Type::PackExpansion:      MarkUsedTemplateParameters(SemaRef,                                 cast<PackExpansionType>(T)->getPattern(), diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp index 92ba095cd6c8..3c1964175b10 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -13,6 +13,7 @@  #include "clang/Sema/SemaInternal.h"  #include "TreeTransform.h"  #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Initialization.h"  #include "clang/Sema/Lookup.h"  #include "clang/Sema/Template.h"  #include "clang/Sema/TemplateDeduction.h" @@ -58,9 +59,13 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,      Result.addOuterTemplateArguments(Innermost);    DeclContext *Ctx = dyn_cast<DeclContext>(D); -  if (!Ctx) +  if (!Ctx) {      Ctx = D->getDeclContext(); - +     +    assert((!D->isTemplateParameter() || !Ctx->isTranslationUnit()) && +           "Template parameter doesn't have its context yet!"); +  } +      while (!Ctx->isFileContext()) {      // Add template arguments from a class template instantiation.      if (ClassTemplateSpecializationDecl *Spec @@ -446,10 +451,15 @@ void Sema::PrintInstantiationStack() {          Diags.Report(Active->PointOfInstantiation, DiagID)            << Function            << Active->InstantiationRange; -      } else { +      } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {          Diags.Report(Active->PointOfInstantiation,                       diag::note_template_static_data_member_def_here) -          << cast<VarDecl>(D) +          << VD +          << Active->InstantiationRange; +      } else { +        Diags.Report(Active->PointOfInstantiation, +                     diag::note_template_type_alias_instantiation_here) +          << cast<TypeAliasTemplateDecl>(D)            << Active->InstantiationRange;        }        break; @@ -918,7 +928,8 @@ TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,      // like it's likely to produce a lot of spurious errors.      if (Keyword != ETK_None && Keyword != ETK_Typename) {        TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword); -      if (!SemaRef.isAcceptableTagRedeclaration(TD, Kind, TagLocation, *Id)) { +      if (!SemaRef.isAcceptableTagRedeclaration(TD, Kind, /*isDefinition*/false, +                                                TagLocation, *Id)) {          SemaRef.Diag(TagLocation, diag::err_use_with_wrong_tag)            << Id            << FixItHint::CreateReplacement(SourceRange(TagLocation), @@ -968,8 +979,7 @@ TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS,        }        TemplateName Template = Arg.getAsTemplate(); -      assert(!Template.isNull() && Template.getAsTemplateDecl() && -             "Wrong kind of template template argument"); +      assert(!Template.isNull() && "Null template template argument");        // We don't ever want to substitute for a qualified template name, since        // the qualifier is handled separately. So, look through the qualified @@ -1384,6 +1394,12 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {    for (unsigned I = 0, E = FP.getNumArgs(); I != E; ++I) {      ParmVarDecl *P = FP.getArg(I); +    // The parameter's type as written might be dependent even if the +    // decayed type was not dependent. +    if (TypeSourceInfo *TSInfo = P->getTypeSourceInfo()) +      if (TSInfo->getType()->isDependentType()) +        return true; +      // TODO: currently we always rebuild expressions.  When we      // properly get lazier about this, we should use the same      // logic to avoid rebuilding prototypes here. @@ -1729,6 +1745,8 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,    TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);    llvm::SmallVector<Decl*, 4> Fields; +  llvm::SmallVector<std::pair<FieldDecl*, FieldDecl*>, 4> +    FieldsWithMemberInitializers;    for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),           MemberEnd = Pattern->decls_end();         Member != MemberEnd; ++Member) { @@ -1751,9 +1769,13 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,      Decl *NewMember = Instantiator.Visit(*Member);      if (NewMember) { -      if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) +      if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) {          Fields.push_back(Field); -      else if (NewMember->isInvalidDecl()) +        FieldDecl *OldField = cast<FieldDecl>(*Member); +        if (OldField->getInClassInitializer()) +          FieldsWithMemberInitializers.push_back(std::make_pair(OldField, +                                                                Field)); +      } else if (NewMember->isInvalidDecl())          Invalid = true;      } else {        // FIXME: Eventually, a NULL return will mean that one of the @@ -1767,6 +1789,43 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,                Fields.data(), Fields.size(), SourceLocation(), SourceLocation(),                0);    CheckCompletedCXXClass(Instantiation); + +  // Attach any in-class member initializers now the class is complete. +  for (unsigned I = 0, N = FieldsWithMemberInitializers.size(); I != N; ++I) { +    FieldDecl *OldField = FieldsWithMemberInitializers[I].first; +    FieldDecl *NewField = FieldsWithMemberInitializers[I].second; +    Expr *OldInit = OldField->getInClassInitializer(); +    ExprResult NewInit = SubstExpr(OldInit, TemplateArgs); + +    // If the initialization is no longer dependent, check it now. +    if ((OldField->getType()->isDependentType() || OldInit->isTypeDependent()) +        && !NewField->getType()->isDependentType() +        && !NewInit.get()->isTypeDependent()) { +      // FIXME: handle list-initialization +      SourceLocation EqualLoc = NewField->getLocation(); +      NewInit = PerformCopyInitialization( +        InitializedEntity::InitializeMember(NewField), EqualLoc, +        NewInit.release()); + +      if (!NewInit.isInvalid()) { +        CheckImplicitConversions(NewInit.get(), EqualLoc); + +        // C++0x [class.base.init]p7: +        //   The initialization of each base and member constitutes a +        //   full-expression. +        NewInit = MaybeCreateExprWithCleanups(NewInit); +      } +    } + +    if (NewInit.isInvalid()) +      NewField->setInvalidDecl(); +    else +      NewField->setInClassInitializer(NewInit.release()); +  } + +  if (!FieldsWithMemberInitializers.empty()) +    ActOnFinishDelayedMemberInitializers(Instantiation); +    if (Instantiation->isInvalidDecl())      Invalid = true;    else { @@ -2009,7 +2068,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,              SuppressNew)            continue; -        if (Function->hasBody()) +        if (Function->isDefined())            continue;          if (TSK == TSK_ExplicitInstantiationDefinition) { @@ -2019,7 +2078,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,            //   specialization and is only an explicit instantiation definition             //   of members whose definition is visible at the point of             //   instantiation. -          if (!Pattern->hasBody()) +          if (!Pattern->isDefined())              continue;            Function->setTemplateSpecializationKind(TSK, PointOfInstantiation); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 6e11ef5bbc5f..e78aa2991e74 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -128,8 +128,8 @@ TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {    return Inst;  } -Decl *TemplateDeclInstantiator::VisitTypedefNameDecl(TypedefNameDecl *D, -                                                     bool IsTypeAlias) { +Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, +                                                           bool IsTypeAlias) {    bool Invalid = false;    TypeSourceInfo *DI = D->getTypeSourceInfo();    if (DI->getType()->isDependentType() || @@ -178,17 +178,62 @@ Decl *TemplateDeclInstantiator::VisitTypedefNameDecl(TypedefNameDecl *D,    SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef);    Typedef->setAccess(D->getAccess()); -  Owner->addDecl(Typedef);    return Typedef;  }  Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { -  return VisitTypedefNameDecl(D, /*IsTypeAlias=*/false); +  Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/false); +  Owner->addDecl(Typedef); +  return Typedef;  }  Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) { -  return VisitTypedefNameDecl(D, /*IsTypeAlias=*/true); +  Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/true); +  Owner->addDecl(Typedef); +  return Typedef; +} + +Decl * +TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { +  // Create a local instantiation scope for this type alias template, which +  // will contain the instantiations of the template parameters. +  LocalInstantiationScope Scope(SemaRef); + +  TemplateParameterList *TempParams = D->getTemplateParameters(); +  TemplateParameterList *InstParams = SubstTemplateParams(TempParams); +  if (!InstParams) +    return 0; + +  TypeAliasDecl *Pattern = D->getTemplatedDecl(); + +  TypeAliasTemplateDecl *PrevAliasTemplate = 0; +  if (Pattern->getPreviousDeclaration()) { +    DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); +    if (Found.first != Found.second) { +      PrevAliasTemplate = dyn_cast<TypeAliasTemplateDecl>(*Found.first); +    } +  } + +  TypeAliasDecl *AliasInst = cast_or_null<TypeAliasDecl>( +    InstantiateTypedefNameDecl(Pattern, /*IsTypeAlias=*/true)); +  if (!AliasInst) +    return 0; + +  TypeAliasTemplateDecl *Inst +    = TypeAliasTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(), +                                    D->getDeclName(), InstParams, AliasInst); +  if (PrevAliasTemplate) +    Inst->setPreviousDeclaration(PrevAliasTemplate); + +  Inst->setAccess(D->getAccess()); + +  if (!PrevAliasTemplate) +    Inst->setInstantiatedFromMemberTemplate(D); +   +  Owner->addDecl(Inst); + +  return Inst;  }  /// \brief Instantiate an initializer, breaking it into separate @@ -432,6 +477,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {                                              D->getLocation(),                                              D->isMutable(),                                              BitWidth, +                                            D->hasInClassInitializer(),                                              D->getTypeSpecStartLoc(),                                              D->getAccess(),                                              0); @@ -1171,7 +1217,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,          D->isThisDeclarationADefinition()) {        // Check for a function body.        const FunctionDecl *Definition = 0; -      if (Function->hasBody(Definition) && +      if (Function->isDefined(Definition) &&            Definition->getTemplateSpecializationKind() == TSK_Undeclared) {          SemaRef.Diag(Function->getLocation(), diag::err_redefinition)             << Function->getDeclName(); @@ -1203,7 +1249,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,          default:            if (const FunctionDecl *RPattern                = R->getTemplateInstantiationPattern()) -            if (RPattern->hasBody(RPattern)) { +            if (RPattern->isDefined(RPattern)) {                SemaRef.Diag(Function->getLocation(), diag::err_redefinition)                   << Function->getDeclName();                SemaRef.Diag(R->getLocation(), diag::note_previous_definition); @@ -1219,6 +1265,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,        PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))      PrincipalDecl->setNonMemberOperator(); +  assert(!D->isDefaulted() && "only methods should be defaulted");    return Function;  } @@ -1451,7 +1498,14 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,      else        Owner->addDecl(DeclToAdd);    } -   + +  if (D->isExplicitlyDefaulted()) { +    SemaRef.SetDeclDefaulted(Method, Method->getLocation()); +  } else { +    assert(!D->isDefaulted() && +           "should not implicitly default uninstantiated function"); +  } +    return Method;  } @@ -2079,8 +2133,8 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,  bool  TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,                                                      FunctionDecl *Tmpl) { -  if (Tmpl->isDeleted()) -    New->setDeleted(); +  if (Tmpl->isDeletedAsWritten()) +    New->setDeletedAsWritten();    // If we are performing substituting explicitly-specified template arguments    // or deduced template arguments into a function template and we reach this @@ -2186,6 +2240,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,      }      Expr *NoexceptExpr = 0;      if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) { +      EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);        ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);        if (E.isUsable())          NoexceptExpr = E.take(); @@ -2255,7 +2310,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,                                           FunctionDecl *Function,                                           bool Recursive,                                           bool DefinitionRequired) { -  if (Function->isInvalidDecl() || Function->hasBody()) +  if (Function->isInvalidDecl() || Function->isDefined())      return;    // Never instantiate an explicit specialization. @@ -2264,12 +2319,19 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,    // Find the function body that we'll be substituting.    const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern(); -  Stmt *Pattern = 0; -  if (PatternDecl) -    Pattern = PatternDecl->getBody(PatternDecl); +  assert(PatternDecl && "instantiating a non-template"); + +  Stmt *Pattern = PatternDecl->getBody(PatternDecl); +  assert(PatternDecl && "template definition is not a template"); +  if (!Pattern) { +    // Try to find a defaulted definition +    PatternDecl->isDefined(PatternDecl); +  } +  assert(PatternDecl && "template definition is not a template");    // Postpone late parsed template instantiations. -  if (PatternDecl->isLateTemplateParsed() && !LateTemplateParser) { +  if (PatternDecl->isLateTemplateParsed() && +      !LateTemplateParser) {      PendingInstantiations.push_back(        std::make_pair(Function, PointOfInstantiation));      return; @@ -2277,13 +2339,13 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,    // Call the LateTemplateParser callback if there a need to late parse    // a templated function definition.  -  if (!Pattern && PatternDecl && PatternDecl->isLateTemplateParsed() && +  if (!Pattern && PatternDecl->isLateTemplateParsed() &&        LateTemplateParser) {      LateTemplateParser(OpaqueParser, PatternDecl);      Pattern = PatternDecl->getBody(PatternDecl);    } -  if (!Pattern) { +  if (!Pattern && !PatternDecl->isDefaulted()) {      if (DefinitionRequired) {        if (Function->getPrimaryTemplate())          Diag(PointOfInstantiation,  @@ -2378,21 +2440,27 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,    MultiLevelTemplateArgumentList TemplateArgs =      getTemplateInstantiationArgs(Function, 0, false, PatternDecl); -  // If this is a constructor, instantiate the member initializers. -  if (const CXXConstructorDecl *Ctor = -        dyn_cast<CXXConstructorDecl>(PatternDecl)) { -    InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor, -                               TemplateArgs); -  } +  if (PatternDecl->isDefaulted()) { +    ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true); -  // Instantiate the function body. -  StmtResult Body = SubstStmt(Pattern, TemplateArgs); +    SetDeclDefaulted(Function, PatternDecl->getLocation()); +  } else { +    // If this is a constructor, instantiate the member initializers. +    if (const CXXConstructorDecl *Ctor = +          dyn_cast<CXXConstructorDecl>(PatternDecl)) { +      InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor, +                                 TemplateArgs); +    } -  if (Body.isInvalid()) -    Function->setInvalidDecl(); -   -  ActOnFinishFunctionBody(Function, Body.get(), -                          /*IsInstantiation=*/true); +    // Instantiate the function body. +    StmtResult Body = SubstStmt(Pattern, TemplateArgs); + +    if (Body.isInvalid()) +      Function->setInvalidDecl(); +     +    ActOnFinishFunctionBody(Function, Body.get(), +                            /*IsInstantiation=*/true); +  }    PerformDependentDiagnostics(PatternDecl, TemplateArgs); @@ -2415,9 +2483,13 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,      PerformPendingInstantiations();      // Restore the set of pending vtables. +    assert(VTableUses.empty() && +           "VTableUses should be empty before it is discarded.");      VTableUses.swap(SavedVTableUses);      // Restore the set of pending implicit instantiations. +    assert(PendingInstantiations.empty() && +           "PendingInstantiations should be empty before it is discarded.");      PendingInstantiations.swap(SavedPendingInstantiations);    }  } @@ -2484,6 +2556,10 @@ void Sema::InstantiateStaticDataMemberDefinition(          == TSK_ExplicitInstantiationDeclaration)      return; +  // If we already have a definition, we're done. +  if (Var->getDefinition()) +    return; +    InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);    if (Inst)      return; @@ -2491,9 +2567,12 @@ void Sema::InstantiateStaticDataMemberDefinition(    // If we're performing recursive template instantiation, create our own    // queue of pending implicit instantiations that we will instantiate later,    // while we're still within our own instantiation context. +  llvm::SmallVector<VTableUse, 16> SavedVTableUses;    std::deque<PendingImplicitInstantiation> SavedPendingInstantiations; -  if (Recursive) +  if (Recursive) { +    VTableUses.swap(SavedVTableUses);      PendingInstantiations.swap(SavedPendingInstantiations); +  }    // Enter the scope of this instantiation. We don't use    // PushDeclContext because we don't have a scope. @@ -2515,11 +2594,23 @@ void Sema::InstantiateStaticDataMemberDefinition(    }    if (Recursive) { +    // Define any newly required vtables. +    DefineUsedVTables(); +      // Instantiate any pending implicit instantiations found during the      // instantiation of this template.      PerformPendingInstantiations(); +    // Restore the set of pending vtables. +    assert(VTableUses.empty() && +           "VTableUses should be empty before it is discarded, " +           "while instantiating static data member."); +    VTableUses.swap(SavedVTableUses); +      // Restore the set of pending implicit instantiations. +    assert(PendingInstantiations.empty() && +           "PendingInstantiations should be empty before it is discarded, " +           "while instantiating static data member.");      PendingInstantiations.swap(SavedPendingInstantiations);    }  } @@ -3115,10 +3206,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,  /// \brief Performs template instantiation for all implicit template  /// instantiations we have seen until this point. -/// -/// \returns true if anything was instantiated. -bool Sema::PerformPendingInstantiations(bool LocalOnly) { -  bool InstantiatedAnything = false; +void Sema::PerformPendingInstantiations(bool LocalOnly) {    while (!PendingLocalImplicitInstantiations.empty() ||           (!LocalOnly && !PendingInstantiations.empty())) {      PendingImplicitInstantiation Inst; @@ -3139,7 +3227,6 @@ bool Sema::PerformPendingInstantiations(bool LocalOnly) {                                  TSK_ExplicitInstantiationDefinition;        InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true,                                      DefinitionRequired); -      InstantiatedAnything = true;        continue;      } @@ -3176,10 +3263,7 @@ bool Sema::PerformPendingInstantiations(bool LocalOnly) {                                TSK_ExplicitInstantiationDefinition;      InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true,                                            DefinitionRequired); -    InstantiatedAnything = true;    } -   -  return InstantiatedAnything;  }  void Sema::PerformDependentDiagnostics(const DeclContext *Pattern, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp index 096d353bccc3..86d3bc170909 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -617,7 +617,8 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {    const DeclSpec &DS = D.getDeclSpec();    switch (DS.getTypeSpecType()) {    case TST_typename: -  case TST_typeofType: { +  case TST_typeofType: +  case TST_underlyingType: {      QualType T = DS.getRepAsType().get();      if (!T.isNull() && T->containsUnexpandedParameterPack())        return true; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp index 00ac1d63dbe7..5fd8afa6acf4 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp @@ -15,6 +15,7 @@  #include "clang/Sema/Template.h"  #include "clang/Basic/OpenCL.h"  #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h"  #include "clang/AST/CXXInheritance.h"  #include "clang/AST/DeclObjC.h"  #include "clang/AST/DeclTemplate.h" @@ -836,6 +837,18 @@ static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) {      }      break;    } +  case DeclSpec::TST_underlyingType: +    Result = S.GetTypeFromParser(DS.getRepAsType()); +    assert(!Result.isNull() && "Didn't get a type for __underlying_type?"); +    Result = S.BuildUnaryTransformType(Result, +                                       UnaryTransformType::EnumUnderlyingType, +                                       DS.getTypeSpecTypeLoc()); +    if (Result.isNull()) { +      Result = Context.IntTy; +      declarator.setInvalidType(true); +    } +    break;  +    case DeclSpec::TST_auto: {      // TypeQuals handled by caller.      Result = Context.getAutoType(QualType()); @@ -1048,6 +1061,9 @@ QualType Sema::BuildPointerType(QualType T,  QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,                                    SourceLocation Loc,                                    DeclarationName Entity) { +  assert(Context.getCanonicalType(T) != Context.OverloadTy &&  +         "Unresolved overloaded function type"); +      // C++0x [dcl.ref]p6:    //   If a typedef (7.1.3), a type template-parameter (14.3.1), or a     //   decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a  @@ -1464,41 +1480,37 @@ static void DiagnoseIgnoredQualifiers(unsigned Quals,    FixItHint VolatileFixIt;    FixItHint RestrictFixIt; +  const SourceManager &SM = S.getSourceManager(); +    // FIXME: The locations here are set kind of arbitrarily. It'd be nicer to    // find a range and grow it to encompass all the qualifiers, regardless of    // the order in which they textually appear.    if (Quals & Qualifiers::Const) {      ConstFixIt = FixItHint::CreateRemoval(ConstQualLoc); -    Loc = ConstQualLoc; -    ++NumQuals;      QualStr = "const"; +    ++NumQuals; +    if (!Loc.isValid() || SM.isBeforeInTranslationUnit(ConstQualLoc, Loc)) +      Loc = ConstQualLoc;    }    if (Quals & Qualifiers::Volatile) {      VolatileFixIt = FixItHint::CreateRemoval(VolatileQualLoc); -    if (NumQuals == 0) { -      Loc = VolatileQualLoc; -      QualStr = "volatile"; -    } else { -      QualStr += " volatile"; -    } +    QualStr += (NumQuals == 0 ? "volatile" : " volatile");      ++NumQuals; +    if (!Loc.isValid() || SM.isBeforeInTranslationUnit(VolatileQualLoc, Loc)) +      Loc = VolatileQualLoc;    }    if (Quals & Qualifiers::Restrict) {      RestrictFixIt = FixItHint::CreateRemoval(RestrictQualLoc); -    if (NumQuals == 0) { -      Loc = RestrictQualLoc; -      QualStr = "restrict"; -    } else { -      QualStr += " restrict"; -    } +    QualStr += (NumQuals == 0 ? "restrict" : " restrict");      ++NumQuals; +    if (!Loc.isValid() || SM.isBeforeInTranslationUnit(RestrictQualLoc, Loc)) +      Loc = RestrictQualLoc;    }    assert(NumQuals > 0 && "No known qualifiers?");    S.Diag(Loc, diag::warn_qual_return_type) -    << QualStr << NumQuals -    << ConstFixIt << VolatileFixIt << RestrictFixIt; +    << QualStr << NumQuals << ConstFixIt << VolatileFixIt << RestrictFixIt;  }  /// GetTypeForDeclarator - Convert the type for the specified @@ -1581,6 +1593,8 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,        Error = 0; // Function prototype        break;      case Declarator::MemberContext: +      if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static) +        break;        switch (cast<TagDecl>(CurContext)->getTagKind()) {        case TTK_Enum: assert(0 && "unhandled tag kind"); break;        case TTK_Struct: Error = 1; /* Struct member */ break; @@ -1601,6 +1615,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,        Error = 7; // Template type argument        break;      case Declarator::AliasDeclContext: +    case Declarator::AliasTemplateContext:        Error = 9; // Type alias        break;      case Declarator::TypeNameContext: @@ -1659,7 +1674,8 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,    // Does this declaration declare a typedef-name?    bool IsTypedefName =      D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef || -    D.getContext() == Declarator::AliasDeclContext; +    D.getContext() == Declarator::AliasDeclContext || +    D.getContext() == Declarator::AliasTemplateContext;    // Walk the DeclTypeInfo, building the recursive type as we go.    // DeclTypeInfos are ordered from the identifier out, which is @@ -1839,7 +1855,8 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,        // anyway.        if (IsTypedefName && FTI.getExceptionSpecType())          Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef) -          << (D.getContext() == Declarator::AliasDeclContext); +          << (D.getContext() == Declarator::AliasDeclContext || +              D.getContext() == Declarator::AliasTemplateContext);        if (!FTI.NumArgs && !FTI.isVariadic && !getLangOptions().CPlusPlus) {          // Simple void foo(), where the incoming T is the result type. @@ -2204,6 +2221,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,      case Declarator::ObjCPrototypeContext: // FIXME: special diagnostic here?      case Declarator::TypeNameContext:      case Declarator::AliasDeclContext: +    case Declarator::AliasTemplateContext:      case Declarator::MemberContext:      case Declarator::BlockContext:      case Declarator::ForContext: @@ -2367,6 +2385,16 @@ namespace {        Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);        TL.setUnderlyingTInfo(TInfo);      } +    void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) { +      // FIXME: This holds only because we only have one unary transform. +      assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType); +      TL.setKWLoc(DS.getTypeSpecTypeLoc()); +      TL.setParensRange(DS.getTypeofParensRange()); +      assert(DS.getRepAsType()); +      TypeSourceInfo *TInfo = 0; +      Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); +      TL.setUnderlyingTInfo(TInfo); +    }      void VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {        // By default, use the source location of the type specifier.        TL.setBuiltinLoc(DS.getTypeSpecTypeLoc()); @@ -2640,13 +2668,17 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {      CheckExtraCXXDefaultArguments(D);      // C++0x [dcl.type]p3: -    //   A type-specifier-seq shall not define a class or enumeration -    //   unless it appears in the type-id of an alias-declaration -    //   (7.1.3). -    if (OwnedTag && OwnedTag->isDefinition() && -        D.getContext() != Declarator::AliasDeclContext) -      Diag(OwnedTag->getLocation(), diag::err_type_defined_in_type_specifier) -        << Context.getTypeDeclType(OwnedTag); +    //   A type-specifier-seq shall not define a class or enumeration unless +    //   it appears in the type-id of an alias-declaration (7.1.3) that is not +    //   the declaration of a template-declaration. +    if (OwnedTag && OwnedTag->isDefinition()) { +      if (D.getContext() == Declarator::AliasTemplateContext) +        Diag(OwnedTag->getLocation(), diag::err_type_defined_in_alias_template) +          << Context.getTypeDeclType(OwnedTag); +      else if (D.getContext() != Declarator::AliasDeclContext) +        Diag(OwnedTag->getLocation(), diag::err_type_defined_in_type_specifier) +          << Context.getTypeDeclType(OwnedTag); +    }    }    return CreateParsedType(T, TInfo); @@ -3213,6 +3245,82 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,    } while ((attrs = next));  } +/// \brief Ensure that the type of the given expression is complete. +/// +/// This routine checks whether the expression \p E has a complete type. If the +/// expression refers to an instantiable construct, that instantiation is +/// performed as needed to complete its type. Furthermore +/// Sema::RequireCompleteType is called for the expression's type (or in the +/// case of a reference type, the referred-to type). +/// +/// \param E The expression whose type is required to be complete. +/// \param PD The partial diagnostic that will be printed out if the type cannot +/// be completed. +/// +/// \returns \c true if the type of \p E is incomplete and diagnosed, \c false +/// otherwise. +bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD, +                                   std::pair<SourceLocation, +                                             PartialDiagnostic> Note) { +  QualType T = E->getType(); + +  // Fast path the case where the type is already complete. +  if (!T->isIncompleteType()) +    return false; + +  // Incomplete array types may be completed by the initializer attached to +  // their definitions. For static data members of class templates we need to +  // instantiate the definition to get this initializer and complete the type. +  if (T->isIncompleteArrayType()) { +    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) { +      if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { +        if (Var->isStaticDataMember() && +            Var->getInstantiatedFromStaticDataMember()) { +           +          MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); +          assert(MSInfo && "Missing member specialization information?"); +          if (MSInfo->getTemplateSpecializationKind() +                != TSK_ExplicitSpecialization) { +            // If we don't already have a point of instantiation, this is it. +            if (MSInfo->getPointOfInstantiation().isInvalid()) { +              MSInfo->setPointOfInstantiation(E->getLocStart()); +               +              // This is a modification of an existing AST node. Notify  +              // listeners. +              if (ASTMutationListener *L = getASTMutationListener()) +                L->StaticDataMemberInstantiated(Var); +            } +             +            InstantiateStaticDataMemberDefinition(E->getExprLoc(), Var); +             +            // Update the type to the newly instantiated definition's type both +            // here and within the expression. +            if (VarDecl *Def = Var->getDefinition()) { +              DRE->setDecl(Def); +              T = Def->getType(); +              DRE->setType(T); +              E->setType(T); +            } +          } +           +          // We still go on to try to complete the type independently, as it +          // may also require instantiations or diagnostics if it remains +          // incomplete. +        } +      } +    } +  } + +  // FIXME: Are there other cases which require instantiating something other +  // than the type to complete the type of an expression? + +  // Look through reference types and complete the referred type. +  if (const ReferenceType *Ref = T->getAs<ReferenceType>()) +    T = Ref->getPointeeType(); + +  return RequireCompleteType(E->getExprLoc(), T, PD, Note); +} +  /// @brief Ensure that the type T is a complete type.  ///  /// This routine checks whether the type @p T is complete in any @@ -3363,3 +3471,27 @@ QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) {    return Context.getDecltypeType(E);  } + +QualType Sema::BuildUnaryTransformType(QualType BaseType, +                                       UnaryTransformType::UTTKind UKind, +                                       SourceLocation Loc) { +  switch (UKind) { +  case UnaryTransformType::EnumUnderlyingType: +    if (!BaseType->isDependentType() && !BaseType->isEnumeralType()) { +      Diag(Loc, diag::err_only_enums_have_underlying_types); +      return QualType(); +    } else { +      QualType Underlying = BaseType; +      if (!BaseType->isDependentType()) { +        EnumDecl *ED = BaseType->getAs<EnumType>()->getDecl(); +        assert(ED && "EnumType has no EnumDecl"); +        DiagnoseUseOfDecl(ED, Loc); +        Underlying = ED->getIntegerType(); +      } +      assert(!Underlying.isNull()); +      return Context.getUnaryTransformType(BaseType, Underlying, +                                        UnaryTransformType::EnumUnderlyingType); +    } +  } +  llvm_unreachable("unknown unary transform type"); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h index 2a71e14265a8..ff2e46a9026b 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h +++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h @@ -21,6 +21,7 @@  #include "clang/Sema/ScopeInfo.h"  #include "clang/AST/Decl.h"  #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h"  #include "clang/AST/Expr.h"  #include "clang/AST/ExprCXX.h"  #include "clang/AST/ExprObjC.h" @@ -701,6 +702,11 @@ public:    /// By default, builds a new TypeOfType with the given underlying type.    QualType RebuildTypeOfType(QualType Underlying); +  /// \brief Build a new unary transform type. +  QualType RebuildUnaryTransformType(QualType BaseType, +                                     UnaryTransformType::UTTKind UKind, +                                     SourceLocation Loc); +    /// \brief Build a new C++0x decltype type.    ///    /// By default, performs semantic analysis when building the decltype type. @@ -855,7 +861,7 @@ public:          case LookupResult::Found:          case LookupResult::FoundOverloaded:          case LookupResult::FoundUnresolvedValue: { -	  NamedDecl *SomeDecl = Result.getRepresentativeDecl(); +          NamedDecl *SomeDecl = Result.getRepresentativeDecl();            unsigned Kind = 0;            if (isa<TypedefDecl>(SomeDecl)) Kind = 1;            else if (isa<TypeAliasDecl>(SomeDecl)) Kind = 2; @@ -863,7 +869,7 @@ public:            SemaRef.Diag(IdLoc, diag::err_tag_reference_non_tag) << Kind;            SemaRef.Diag(SomeDecl->getLocation(), diag::note_declared_at);            break; -	} +        }          default:            // FIXME: Would be nice to highlight just the source range.            SemaRef.Diag(IdLoc, diag::err_not_tag_in_scope) @@ -873,7 +879,8 @@ public:        return QualType();      } -    if (!SemaRef.isAcceptableTagRedeclaration(Tag, Kind, IdLoc, *Id)) { +    if (!SemaRef.isAcceptableTagRedeclaration(Tag, Kind, /*isDefinition*/false, +                                              IdLoc, *Id)) {        SemaRef.Diag(KeywordLoc, diag::err_use_with_wrong_tag) << Id;        SemaRef.Diag(Tag->getLocation(), diag::note_previous_use);        return QualType(); @@ -1372,7 +1379,7 @@ public:                                           UnaryExprOrTypeTrait ExprKind,                                           SourceRange R) {      ExprResult Result -      = getSema().CreateUnaryExprOrTypeTraitExpr(SubExpr, OpLoc, ExprKind, R); +      = getSema().CreateUnaryExprOrTypeTraitExpr(SubExpr, OpLoc, ExprKind);      if (Result.isInvalid())        return ExprError(); @@ -2567,9 +2574,13 @@ TreeTransform<Derived>::TransformNestedNameSpecifierLoc(                    Q.getLocalEndLoc());          break;        } -       -      SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag)  -        << TL.getType() << SS.getRange(); +      // If the nested-name-specifier is an invalid type def, don't emit an +      // error because a previous error should have already been emitted. +      TypedefTypeLoc* TTL = dyn_cast<TypedefTypeLoc>(&TL); +      if (!TTL || !TTL->getTypedefNameDecl()->isInvalidDecl()) { +        SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag)  +          << TL.getType() << SS.getRange(); +      }        return NestedNameSpecifierLoc();      }      } @@ -4154,6 +4165,29 @@ QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,  }  template<typename Derived> +QualType TreeTransform<Derived>::TransformUnaryTransformType( +                                                            TypeLocBuilder &TLB, +                                                     UnaryTransformTypeLoc TL) { +  QualType Result = TL.getType(); +  if (Result->isDependentType()) { +    const UnaryTransformType *T = TL.getTypePtr(); +    QualType NewBase = +      getDerived().TransformType(TL.getUnderlyingTInfo())->getType(); +    Result = getDerived().RebuildUnaryTransformType(NewBase, +                                                    T->getUTTKind(), +                                                    TL.getKWLoc()); +    if (Result.isNull()) +      return QualType(); +  } + +  UnaryTransformTypeLoc NewTL = TLB.push<UnaryTransformTypeLoc>(Result); +  NewTL.setKWLoc(TL.getKWLoc()); +  NewTL.setParensRange(TL.getParensRange()); +  NewTL.setUnderlyingTInfo(TL.getUnderlyingTInfo()); +  return Result; +} + +template<typename Derived>  QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB,                                                     AutoTypeLoc TL) {    const AutoType *T = TL.getTypePtr(); @@ -4389,6 +4423,23 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType(                                                     NewTemplateArgs);    if (!Result.isNull()) { +    // Specializations of template template parameters are represented as +    // TemplateSpecializationTypes, and substitution of type alias templates +    // within a dependent context can transform them into +    // DependentTemplateSpecializationTypes. +    if (isa<DependentTemplateSpecializationType>(Result)) { +      DependentTemplateSpecializationTypeLoc NewTL +        = TLB.push<DependentTemplateSpecializationTypeLoc>(Result); +      NewTL.setKeywordLoc(TL.getTemplateNameLoc()); +      NewTL.setQualifierLoc(NestedNameSpecifierLoc()); +      NewTL.setNameLoc(TL.getTemplateNameLoc()); +      NewTL.setLAngleLoc(TL.getLAngleLoc()); +      NewTL.setRAngleLoc(TL.getRAngleLoc()); +      for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) +        NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo()); +      return Result; +    } +      TemplateSpecializationTypeLoc NewTL        = TLB.push<TemplateSpecializationTypeLoc>(Result);      NewTL.setTemplateNameLoc(TL.getTemplateNameLoc()); @@ -4478,6 +4529,23 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,    if (NamedT.isNull())      return QualType(); +  // C++0x [dcl.type.elab]p2: +  //   If the identifier resolves to a typedef-name or the simple-template-id +  //   resolves to an alias template specialization, the +  //   elaborated-type-specifier is ill-formed. +  if (T->getKeyword() != ETK_None && T->getKeyword() != ETK_Typename) { +    if (const TemplateSpecializationType *TST = +          NamedT->getAs<TemplateSpecializationType>()) { +      TemplateName Template = TST->getTemplateName(); +      if (TypeAliasTemplateDecl *TAT = +          dyn_cast_or_null<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) { +        SemaRef.Diag(TL.getNamedTypeLoc().getBeginLoc(), +                     diag::err_tag_reference_non_tag) << 4; +        SemaRef.Diag(TAT->getLocation(), diag::note_declared_at); +      } +    } +  } +    QualType Result = TL.getType();    if (getDerived().AlwaysRebuild() ||        QualifierLoc != TL.getQualifierLoc() || @@ -6629,8 +6697,12 @@ template<typename Derived>  ExprResult  TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {    DeclContext *DC = getSema().getFunctionLevelDeclContext(); -  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC); -  QualType T = MD->getThisType(getSema().Context); +  QualType T; +  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) +    T = MD->getThisType(getSema().Context); +  else +    T = getSema().Context.getPointerType( +      getSema().Context.getRecordType(cast<CXXRecordDecl>(DC)));    if (!getDerived().AlwaysRebuild() && T == E->getType())      return SemaRef.Owned(E); @@ -7449,6 +7521,7 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)  template<typename Derived>  ExprResult  TreeTransform<Derived>::TransformCXXNoexceptExpr(CXXNoexceptExpr *E) { +  EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);    ExprResult SubExpr = getDerived().TransformExpr(E->getOperand());    if (SubExpr.isInvalid())      return ExprError(); @@ -7700,6 +7773,11 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {    BlockScopeInfo *blockScope = SemaRef.getCurBlock();    blockScope->TheDecl->setIsVariadic(oldBlock->isVariadic()); +  // We built a new blockScopeInfo in call to ActOnBlockStart +  // in above, CapturesCXXThis need be set here from the block +  // expression. +  blockScope->CapturesCXXThis = oldBlock->capturesCXXThis(); +      llvm::SmallVector<ParmVarDecl*, 4> params;    llvm::SmallVector<QualType, 4> paramTypes; @@ -7759,22 +7837,21 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {  #ifndef NDEBUG    // In builds with assertions, make sure that we captured everything we    // captured before. +  if (!SemaRef.getDiagnostics().hasErrorOccurred()) { +    for (BlockDecl::capture_iterator i = oldBlock->capture_begin(), +           e = oldBlock->capture_end(); i != e; ++i) { +      VarDecl *oldCapture = i->getVariable(); + +      // Ignore parameter packs. +      if (isa<ParmVarDecl>(oldCapture) && +          cast<ParmVarDecl>(oldCapture)->isParameterPack()) +        continue; -  if (oldBlock->capturesCXXThis()) assert(blockScope->CapturesCXXThis); - -  for (BlockDecl::capture_iterator i = oldBlock->capture_begin(), -         e = oldBlock->capture_end(); i != e; ++i) { -    VarDecl *oldCapture = i->getVariable(); - -    // Ignore parameter packs. -    if (isa<ParmVarDecl>(oldCapture) && -        cast<ParmVarDecl>(oldCapture)->isParameterPack()) -      continue; - -    VarDecl *newCapture = -      cast<VarDecl>(getDerived().TransformDecl(E->getCaretLocation(), -                                               oldCapture)); -    assert(blockScope->CaptureMap.count(newCapture)); +      VarDecl *newCapture = +        cast<VarDecl>(getDerived().TransformDecl(E->getCaretLocation(), +                                                 oldCapture)); +      assert(blockScope->CaptureMap.count(newCapture)); +    }    }  #endif @@ -7805,6 +7882,13 @@ TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) {                                           ND, NameInfo, 0);  } +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformAsTypeExpr(AsTypeExpr *E) { +  assert(false && "Cannot transform asType expressions yet"); +  return SemaRef.Owned(E); +} +    //===----------------------------------------------------------------------===//  // Type reconstruction  //===----------------------------------------------------------------------===// @@ -8010,6 +8094,13 @@ QualType TreeTransform<Derived>::RebuildDecltypeType(Expr *E,  }  template<typename Derived> +QualType TreeTransform<Derived>::RebuildUnaryTransformType(QualType BaseType, +                                            UnaryTransformType::UTTKind UKind, +                                            SourceLocation Loc) { +  return SemaRef.BuildUnaryTransformType(BaseType, UKind, Loc); +} + +template<typename Derived>  QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(                                                        TemplateName Template,                                               SourceLocation TemplateNameLoc,  | 
