diff options
36 files changed, 548 insertions, 392 deletions
diff --git a/docs/ReleaseNotes.html b/docs/ReleaseNotes.html index d05c4b6939d1f..f49f7f851902e 100644 --- a/docs/ReleaseNotes.html +++ b/docs/ReleaseNotes.html @@ -118,8 +118,8 @@ modes.</p>  <!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->  <h4 id="cxx11changes">C++11 Feature Support</h4> -<p>Clang 3.1 adds support for -<a href="http://clang.llvm.org/cxx_status.html#cxx11">more of the language +<p>Clang 3.1 supports +<a href="http://clang.llvm.org/cxx_status.html#cxx11">most of the language  features</a> added in the latest ISO C++ standard,  <a href="http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=50372">C++ 2011</a>.  Use <code>-std=c++11</code> or <code>-std=gnu++11</code> to enable support for diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index ac7ab0f9d1d98..0c47f2e486f3e 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -64,9 +64,6 @@ public:    /// \brief Return the TypeLoc wrapper for the type source info.    TypeLoc getTypeLoc() const; // implemented in TypeLoc.h -   -  /// \brief Override the type stored in this TypeSourceInfo. Use with caution! -  void overrideType(QualType T) { Ty = T; }  };  /// TranslationUnitDecl - The top declaration context. diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 957f05b664265..c183da7a6ac90 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -410,8 +410,6 @@ def ext_ellipsis_exception_spec : Extension<    "exception specification of '...' is a Microsoft extension">;  def err_dynamic_and_noexcept_specification : Error<    "cannot have both throw() and noexcept() clause on the same function">; -def err_except_spec_unparsed : Error< -  "unexpected end of exception specification">;  def warn_cxx98_compat_noexcept_decl : Warning<    "noexcept specifications are incompatible with C++98">,    InGroup<CXX98Compat>, DefaultIgnore; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index fe0ef3068167d..2e4d34dff0ba5 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -105,7 +105,6 @@ TOK(eod)                 // End of preprocessing directive (end of line inside a                           // directive).  TOK(code_completion)     // Code completion marker  TOK(cxx_defaultarg_end)  // C++ default argument end marker -TOK(cxx_exceptspec_end)  // C++ exception-specification end marker  // C99 6.4.9: Comments.  TOK(comment)             // Comment (only in -E -C[C] mode) diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index de62ed2def53d..0ae5dc8e03614 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -584,11 +584,15 @@ private:    class TentativeParsingAction {      Parser &P;      Token PrevTok; +    unsigned short PrevParenCount, PrevBracketCount, PrevBraceCount;      bool isActive;    public:      explicit TentativeParsingAction(Parser& p) : P(p) {        PrevTok = P.Tok; +      PrevParenCount = P.ParenCount; +      PrevBracketCount = P.BracketCount; +      PrevBraceCount = P.BraceCount;        P.PP.EnableBacktrackAtThisPos();        isActive = true;      } @@ -601,6 +605,9 @@ private:        assert(isActive && "Parsing action was finished!");        P.PP.Backtrack();        P.Tok = PrevTok; +      P.ParenCount = PrevParenCount; +      P.BracketCount = PrevBracketCount; +      P.BraceCount = PrevBraceCount;        isActive = false;      }      ~TentativeParsingAction() { @@ -1422,12 +1429,10 @@ private:    ExprResult ParseThrowExpression();    ExceptionSpecificationType tryParseExceptionSpecification( -                    bool Delayed,                      SourceRange &SpecificationRange,                      SmallVectorImpl<ParsedType> &DynamicExceptions,                      SmallVectorImpl<SourceRange> &DynamicExceptionRanges, -                    ExprResult &NoexceptExpr, -                    CachedTokens *&ExceptionSpecTokens); +                    ExprResult &NoexceptExpr);    // EndLoc is filled with the location of the last token of the specification.    ExceptionSpecificationType ParseDynamicExceptionSpecification( diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 2f3dda408e328..67fd3939f35de 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -1150,10 +1150,6 @@ struct DeclaratorChunk {        /// \brief Pointer to the expression in the noexcept-specifier of this        /// function, if it has one.        Expr *NoexceptExpr; -   -      /// \brief Pointer to the cached tokens for an exception-specification -      /// that has not yet been parsed. -      CachedTokens *ExceptionSpecTokens;      };      /// TrailingReturnType - If this isn't null, it's the trailing return type @@ -1176,8 +1172,6 @@ struct DeclaratorChunk {          delete[] ArgInfo;        if (getExceptionSpecType() == EST_Dynamic)          delete[] Exceptions; -      else if (getExceptionSpecType() == EST_Delayed) -        delete ExceptionSpecTokens;      }      /// isKNRPrototype - Return true if this is a K&R style identifier list, @@ -1353,7 +1347,6 @@ struct DeclaratorChunk {                                       SourceRange *ExceptionRanges,                                       unsigned NumExceptions,                                       Expr *NoexceptExpr, -                                     CachedTokens *ExceptionSpecTokens,                                       SourceLocation LocalRangeBegin,                                       SourceLocation LocalRangeEnd,                                       Declarator &TheDeclarator, diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index 4433843ff861f..0dd68875a9ec2 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -225,7 +225,9 @@ public:    /// \brief Create the initialization entity for a temporary.    static InitializedEntity InitializeTemporary(QualType Type) { -    return InitializedEntity(EK_Temporary, SourceLocation(), Type); +    InitializedEntity Result(EK_Temporary, SourceLocation(), Type); +    Result.TypeInfo = 0; +    return Result;    }    /// \brief Create the initialization entity for a temporary. diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 8ac7c3ee01a33..c8767b6f9601e 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -331,6 +331,11 @@ public:    /// cycle detection at the end of the TU.    DelegatingCtorDeclsType DelegatingCtorDecls; +  /// \brief All the destructors seen during a class definition that had their +  /// exception spec computation delayed because it depended on an unparsed +  /// exception spec. +  SmallVector<CXXDestructorDecl*, 2> DelayedDestructorExceptionSpecs; +    /// \brief All the overriding destructors seen during a class definition    /// (there could be multiple due to nested classes) that had their exception    /// spec checks delayed, plus the overridden destructor. @@ -653,23 +658,19 @@ public:    /// SpecialMemberOverloadResult - The overloading result for a special member    /// function.    /// -  /// This is basically a wrapper around PointerIntPair. The lowest bit of the -  /// integer is used to determine whether we have a parameter qualification -  /// match, the second-lowest is whether we had success in resolving the -  /// overload to a unique non-deleted function. -  /// -  /// The ConstParamMatch bit represents whether, when looking up a copy -  /// constructor or assignment operator, we found a potential copy -  /// constructor/assignment operator whose first parameter is const-qualified. -  /// This is used for determining parameter types of other objects and is -  /// utterly meaningless on other types of special members. +  /// This is basically a wrapper around PointerIntPair. The lowest bits of the +  /// integer are used to determine whether overload resolution succeeded, and +  /// whether, when looking up a copy constructor or assignment operator, we +  /// found a potential copy constructor/assignment operator whose first +  /// parameter is const-qualified. This is used for determining parameter types +  /// of other objects and is utterly meaningless on other types of special +  /// members.    class SpecialMemberOverloadResult : public llvm::FastFoldingSetNode {    public:      enum Kind {        NoMemberOrDeleted,        Ambiguous, -      SuccessNonConst, -      SuccessConst +      Success      };    private: @@ -685,9 +686,6 @@ public:      Kind getKind() const { return static_cast<Kind>(Pair.getInt()); }      void setKind(Kind K) { Pair.setInt(K); } - -    bool hasSuccess() const { return getKind() >= SuccessNonConst; } -    bool hasConstParamMatch() const { return getKind() == SuccessConst; }    };    /// \brief A cache of special member function overload resolution results @@ -1909,11 +1907,9 @@ public:    DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);    CXXConstructorDecl *LookupDefaultConstructor(CXXRecordDecl *Class);    CXXConstructorDecl *LookupCopyingConstructor(CXXRecordDecl *Class, -                                               unsigned Quals, -                                               bool *ConstParam = 0); +                                               unsigned Quals);    CXXMethodDecl *LookupCopyingAssignment(CXXRecordDecl *Class, unsigned Quals, -                                         bool RValueThis, unsigned ThisQuals, -                                         bool *ConstParam = 0); +                                         bool RValueThis, unsigned ThisQuals);    CXXConstructorDecl *LookupMovingConstructor(CXXRecordDecl *Class);    CXXMethodDecl *LookupMovingAssignment(CXXRecordDecl *Class, bool RValueThis,                                          unsigned ThisQuals); @@ -3158,16 +3154,6 @@ public:                                     llvm::SmallVectorImpl<QualType> &Exceptions,                                     FunctionProtoType::ExtProtoInfo &EPI); -  /// \brief Add an exception-specification to the given member function -  /// (or member function template). The exception-specification was parsed -  /// after the method itself was declared. -  void actOnDelayedExceptionSpecification(Decl *Method, -         ExceptionSpecificationType EST, -         SourceRange SpecificationRange, -         ArrayRef<ParsedType> DynamicExceptions, -         ArrayRef<SourceRange> DynamicExceptionRanges, -         Expr *NoexceptExpr); -    /// \brief Determine if a special member function should have a deleted    /// definition when it is defaulted.    bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, @@ -3205,7 +3191,8 @@ public:    /// C++11 says that user-defined destructors with no exception spec get one    /// that looks as if the destructor was implicitly declared.    void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, -                                     CXXDestructorDecl *Destructor); +                                     CXXDestructorDecl *Destructor, +                                     bool WasDelayed = false);    /// \brief Declare all inherited constructors for the given class.    /// @@ -4043,6 +4030,7 @@ public:                                           SourceLocation LBrac,                                           SourceLocation RBrac,                                           AttributeList *AttrList); +  void ActOnFinishCXXMemberDecls();    void ActOnReenterTemplateScope(Scope *S, Decl *Template);    void ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D); diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp index 6e5da25259738..1c7e6b62f8364 100644 --- a/lib/Analysis/UninitializedValues.cpp +++ b/lib/Analysis/UninitializedValues.cpp @@ -168,7 +168,8 @@ static const BinaryOperator *getLogicalOperatorInChain(const CFGBlock *block) {    if (block->empty())      return 0; -  const CFGStmt *cstmt = block->front().getAs<CFGStmt>(); +  CFGElement front = block->front(); +  const CFGStmt *cstmt = front.getAs<CFGStmt>();    if (!cstmt)      return 0; diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp index 8cb238632b780..cd16b4b02745a 100644 --- a/lib/Basic/Version.cpp +++ b/lib/Basic/Version.cpp @@ -32,7 +32,7 @@ std::string getClangRepositoryPath() {    // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us    // pick up a tag in an SVN export, for example. -  static StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/branches/release_31/lib/Basic/Version.cpp $"); +  static StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_31/final/lib/Basic/Version.cpp $");    if (URL.empty()) {      URL = SVNRepository.slice(SVNRepository.find(':'),                                SVNRepository.find("/lib/Basic")); diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 81657d80661cf..7f9ed9a753057 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -1830,6 +1830,7 @@ enum LinuxDistro {    OpenSuse11_3,    OpenSuse11_4,    OpenSuse12_1, +  OpenSuse12_2,    UbuntuHardy,    UbuntuIntrepid,    UbuntuJaunty, @@ -1848,7 +1849,7 @@ static bool IsRedhat(enum LinuxDistro Distro) {  }  static bool IsOpenSuse(enum LinuxDistro Distro) { -  return Distro >= OpenSuse11_3 && Distro <= OpenSuse12_1; +  return Distro >= OpenSuse11_3 && Distro <= OpenSuse12_2;  }  static bool IsDebian(enum LinuxDistro Distro) { @@ -1925,6 +1926,7 @@ static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) {        .StartsWith("openSUSE 11.3", OpenSuse11_3)        .StartsWith("openSUSE 11.4", OpenSuse11_4)        .StartsWith("openSUSE 12.1", OpenSuse12_1) +      .StartsWith("openSUSE 12.2", OpenSuse12_2)        .Default(UnknownDistro);    bool Exists; diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index f04d76723b6f5..c7b29d9ba28e6 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -348,77 +348,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {        LM.DefaultArgs[I].Toks = 0;      }    } -   -  // Parse a delayed exception-specification, if there is one. -  if (CachedTokens *Toks = LM.ExceptionSpecTokens) { -    // Save the current token position. -    SourceLocation origLoc = Tok.getLocation(); -     -    // Parse the default argument from its saved token stream. -    Toks->push_back(Tok); // So that the current token doesn't get lost -    PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false); -     -    // Consume the previously-pushed token. -    ConsumeAnyToken(); -     -    // C++11 [expr.prim.general]p3: -    //   If a declaration declares a member function or member function  -    //   template of a class X, the expression this is a prvalue of type  -    //   "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq -    //   and the end of the function-definition, member-declarator, or  -    //   declarator. -    CXXMethodDecl *Method; -    if (FunctionTemplateDecl *FunTmpl -          = dyn_cast<FunctionTemplateDecl>(LM.Method)) -      Method = cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); -    else -      Method = cast<CXXMethodDecl>(LM.Method); -     -    Sema::CXXThisScopeRAII ThisScope(Actions, Method->getParent(), -                                     Method->getTypeQualifiers(), -                                     getLangOpts().CPlusPlus0x); - -    // Parse the exception-specification. -    SourceRange SpecificationRange; -    SmallVector<ParsedType, 4> DynamicExceptions; -    SmallVector<SourceRange, 4> DynamicExceptionRanges; -    ExprResult NoexceptExpr; -    CachedTokens *ExceptionSpecTokens; -     -    ExceptionSpecificationType EST -      = tryParseExceptionSpecification(/*Delayed=*/false, SpecificationRange, -                                       DynamicExceptions, -                                       DynamicExceptionRanges, NoexceptExpr, -                                       ExceptionSpecTokens); - -    // Clean up the remaining tokens. -    if (Tok.is(tok::cxx_exceptspec_end)) -      ConsumeToken(); -    else if (EST != EST_None) -      Diag(Tok.getLocation(), diag::err_except_spec_unparsed); - -    // Attach the exception-specification to the method. -    if (EST != EST_None) -      Actions.actOnDelayedExceptionSpecification(LM.Method, EST, -                                                 SpecificationRange, -                                                 DynamicExceptions, -                                                 DynamicExceptionRanges, -                                                 NoexceptExpr.isUsable()? -                                                   NoexceptExpr.get() : 0); -           -    assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, -                                                            Tok.getLocation()) && -           "tryParseExceptionSpecification went over the exception tokens!"); -         -    // There could be leftover tokens (e.g. because of an error). -    // Skip through until we reach the original token position. -    while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) -      ConsumeAnyToken(); -     -    delete LM.ExceptionSpecTokens; -    LM.ExceptionSpecTokens = 0;     -  } -   +    PrototypeScope.Exit();    // Finish the delayed C++ method declaration. diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 932ffb440fd27..7995e68d3f274 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -4197,7 +4197,6 @@ void Parser::ParseFunctionDeclarator(Declarator &D,    SmallVector<ParsedType, 2> DynamicExceptions;    SmallVector<SourceRange, 2> DynamicExceptionRanges;    ExprResult NoexceptExpr; -  CachedTokens *ExceptionSpecTokens = 0;    ParsedAttributes FnAttrs(AttrFactory);    ParsedType TrailingReturnType; @@ -4264,18 +4263,12 @@ void Parser::ParseFunctionDeclarator(Declarator &D,                                 dyn_cast<CXXRecordDecl>(Actions.CurContext),                                 DS.getTypeQualifiers(),                                 IsCXX11MemberFunction); -       +        // Parse exception-specification[opt]. -      bool Delayed = (D.getContext() == Declarator::MemberContext && -                      D.getDeclSpec().getStorageClassSpec() -                        != DeclSpec::SCS_typedef && -                      !D.getDeclSpec().isFriendSpecified()); -      ESpecType = tryParseExceptionSpecification(Delayed, -                                                 ESpecRange, +      ESpecType = tryParseExceptionSpecification(ESpecRange,                                                   DynamicExceptions,                                                   DynamicExceptionRanges, -                                                 NoexceptExpr, -                                                 ExceptionSpecTokens); +                                                 NoexceptExpr);        if (ESpecType != EST_None)          EndLoc = ESpecRange.getEnd(); @@ -4310,7 +4303,6 @@ void Parser::ParseFunctionDeclarator(Declarator &D,                                               DynamicExceptions.size(),                                               NoexceptExpr.isUsable() ?                                                 NoexceptExpr.get() : 0, -                                             ExceptionSpecTokens,                                               Tracker.getOpenLocation(),                                                EndLoc, D,                                               TrailingReturnType), diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index b9b51d7518228..5e6c4f50e0367 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1535,34 +1535,16 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const {  }  /// \brief If the given declarator has any parts for which parsing has to be -/// delayed, e.g., default arguments or an exception-specification, create a -/// late-parsed method declaration record to handle the parsing at the end of -/// the class definition. +/// delayed, e.g., default arguments, create a late-parsed method declaration +/// record to handle the parsing at the end of the class definition.  void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,                                              Decl *ThisDecl) {    // We just declared a member function. If this member function -  // has any default arguments or an exception-specification, we'll need to -  // parse them later. +  // has any default arguments, we'll need to parse them later.    LateParsedMethodDeclaration *LateMethod = 0;    DeclaratorChunk::FunctionTypeInfo &FTI      = DeclaratorInfo.getFunctionTypeInfo(); -   -  // If there was a delayed exception-specification, hold onto its tokens. -  if (FTI.getExceptionSpecType() == EST_Delayed) { -    // Push this method onto the stack of late-parsed method -    // declarations. -    LateMethod = new LateParsedMethodDeclaration(this, ThisDecl); -    getCurrentClass().LateParsedDeclarations.push_back(LateMethod); -    LateMethod->TemplateScope = getCurScope()->isTemplateParamScope(); - -    // Stash the exception-specification tokens in the late-pased mthod. -    LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens; -    FTI.ExceptionSpecTokens = 0; -    // Reserve space for the parameters. -    LateMethod->DefaultArgs.reserve(FTI.NumArgs); -  } -      for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) {      if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) {        if (!LateMethod) { @@ -1846,7 +1828,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,      // Parse the first declarator.      ParseDeclarator(DeclaratorInfo); -    // Error parsin g the declarator? +    // Error parsing the declarator?      if (!DeclaratorInfo.hasName()) {        // If so, skip until the semi-colon or a }.        SkipUntil(tok::r_brace, true, true); @@ -2065,7 +2047,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,        DeclsInGroup.push_back(ThisDecl);      } -    if (DeclaratorInfo.isFunctionDeclarator() && +    if (ThisDecl && DeclaratorInfo.isFunctionDeclarator() &&          DeclaratorInfo.getDeclSpec().getStorageClassSpec()            != DeclSpec::SCS_typedef) {        HandleMemberFunctionDeclDelays(DeclaratorInfo, ThisDecl); @@ -2358,7 +2340,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,    // C++11 [class.mem]p2:    //   Within the class member-specification, the class is regarded as complete -  //   within function bodies, default arguments, exception-specifications, and +  //   within function bodies, default arguments, and    //   brace-or-equal-initializers for non-static data members (including such    //   things in nested classes).    if (TagDecl && NonNestedClass) { @@ -2369,6 +2351,10 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,      SourceLocation SavedPrevTokLocation = PrevTokLocation;      ParseLexedAttributes(getCurrentClass());      ParseLexedMethodDeclarations(getCurrentClass()); + +    // We've finished with all pending member declarations. +    Actions.ActOnFinishCXXMemberDecls(); +      ParseLexedMemberInitializers(getCurrentClass());      ParseLexedMethodDefs(getCurrentClass());      PrevTokLocation = SavedPrevTokLocation; @@ -2555,63 +2541,13 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {  ///         'noexcept'  ///         'noexcept' '(' constant-expression ')'  ExceptionSpecificationType -Parser::tryParseExceptionSpecification(bool Delayed, +Parser::tryParseExceptionSpecification(                      SourceRange &SpecificationRange,                      SmallVectorImpl<ParsedType> &DynamicExceptions,                      SmallVectorImpl<SourceRange> &DynamicExceptionRanges, -                    ExprResult &NoexceptExpr, -                    CachedTokens *&ExceptionSpecTokens) { +                    ExprResult &NoexceptExpr) {    ExceptionSpecificationType Result = EST_None; -  ExceptionSpecTokens = 0; -   -  // Handle delayed parsing of exception-specifications. -  if (Delayed) { -    if (Tok.isNot(tok::kw_throw) && Tok.isNot(tok::kw_noexcept)) -      return EST_None; - -    // Consume and cache the starting token. -    bool IsNoexcept = Tok.is(tok::kw_noexcept); -    Token StartTok = Tok; -    SpecificationRange = SourceRange(ConsumeToken()); - -    // Check for a '('. -    if (!Tok.is(tok::l_paren)) { -      // If this is a bare 'noexcept', we're done. -      if (IsNoexcept) { -        Diag(Tok, diag::warn_cxx98_compat_noexcept_decl); -        NoexceptExpr = 0; -        return EST_BasicNoexcept; -      } -       -      Diag(Tok, diag::err_expected_lparen_after) << "throw"; -      return EST_DynamicNone; -    } -     -    // Cache the tokens for the exception-specification. -    ExceptionSpecTokens = new CachedTokens; -    ExceptionSpecTokens->push_back(StartTok); // 'throw' or 'noexcept' -    ExceptionSpecTokens->push_back(Tok); // '(' -    SpecificationRange.setEnd(ConsumeParen()); // '(' -     -    if (!ConsumeAndStoreUntil(tok::r_paren, *ExceptionSpecTokens, -                              /*StopAtSemi=*/true, -                              /*ConsumeFinalToken=*/true)) { -      NoexceptExpr = 0; -      delete ExceptionSpecTokens; -      ExceptionSpecTokens = 0; -      return IsNoexcept? EST_BasicNoexcept : EST_DynamicNone; -    } -    SpecificationRange.setEnd(Tok.getLocation()); -     -    // Add the 'stop' token. -    Token End; -    End.startToken(); -    End.setKind(tok::cxx_exceptspec_end); -    End.setLocation(Tok.getLocation()); -    ExceptionSpecTokens->push_back(End); -    return EST_Delayed; -  } -   +    // See if there's a dynamic specification.    if (Tok.is(tok::kw_throw)) {      Result = ParseDynamicExceptionSpecification(SpecificationRange, diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index b6a027b0d7943..6d31396cc0166 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -2392,7 +2392,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {                                                         SourceLocation(),                                                         EST_None,                                                         SourceLocation(), -                                                       0, 0, 0, 0, 0, +                                                       0, 0, 0, 0,                                                         CaretLoc, CaretLoc,                                                         ParamInfo),                            attrs, CaretLoc); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index ae6ad0b275b62..715218448a3e9 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -780,13 +780,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(      llvm::SmallVector<ParsedType, 2> DynamicExceptions;      llvm::SmallVector<SourceRange, 2> DynamicExceptionRanges;      ExprResult NoexceptExpr; -    CachedTokens *ExceptionSpecTokens; -    ESpecType = tryParseExceptionSpecification(/*Delayed=*/false, -                                               ESpecRange, +    ESpecType = tryParseExceptionSpecification(ESpecRange,                                                 DynamicExceptions,                                                 DynamicExceptionRanges, -                                               NoexceptExpr, -                                               ExceptionSpecTokens); +                                               NoexceptExpr);      if (ESpecType != EST_None)        DeclEndLoc = ESpecRange.getEnd(); @@ -821,7 +818,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(                                             DynamicExceptions.size(),                                             NoexceptExpr.isUsable() ?                                               NoexceptExpr.get() : 0, -                                           0,                                             DeclLoc, DeclEndLoc, D,                                             TrailingReturnType),                    Attr, DeclEndLoc); @@ -867,7 +863,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(                       /*ExceptionRanges=*/0,                       /*NumExceptions=*/0,                       /*NoexceptExpr=*/0, -                     /*ExceptionSpecTokens=*/0,                       DeclLoc, DeclEndLoc, D,                       TrailingReturnType),                    Attr, DeclEndLoc); diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index fe63e359a19a6..b531accf868ae 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -162,7 +162,6 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,                                               SourceRange *ExceptionRanges,                                               unsigned NumExceptions,                                               Expr *NoexceptExpr, -                                             CachedTokens *ExceptionSpecTokens,                                               SourceLocation LocalRangeBegin,                                               SourceLocation LocalRangeEnd,                                               Declarator &TheDeclarator, @@ -227,10 +226,6 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,    case EST_ComputedNoexcept:      I.Fun.NoexceptExpr = NoexceptExpr;      break; -       -  case EST_Delayed: -    I.Fun.ExceptionSpecTokens = ExceptionSpecTokens; -    break;    }    return I;  } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 1550993079a78..1227e92f76eb1 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -7635,7 +7635,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,                                               SourceLocation(), SourceLocation(),                                               SourceLocation(),                                               EST_None, SourceLocation(), -                                             0, 0, 0, 0, 0, Loc, Loc, D), +                                             0, 0, 0, 0, Loc, Loc, D),                  DS.getAttributes(),                  SourceLocation());    D.SetIdentifier(&II, Loc); @@ -9784,21 +9784,6 @@ 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()); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 1d251b9eb74b2..c861072ad749d 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -7319,15 +7319,42 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,    }  } +/// \brief Perform any semantic analysis which needs to be delayed until all +/// pending class member declarations have been parsed. +void Sema::ActOnFinishCXXMemberDecls() { +  // Now we have parsed all exception specifications, determine the implicit +  // exception specifications for destructors. +  for (unsigned i = 0, e = DelayedDestructorExceptionSpecs.size(); +       i != e; ++i) { +    CXXDestructorDecl *Dtor = DelayedDestructorExceptionSpecs[i]; +    AdjustDestructorExceptionSpec(Dtor->getParent(), Dtor, true); +  } +  DelayedDestructorExceptionSpecs.clear(); + +  // Perform any deferred checking of exception specifications for virtual +  // destructors. +  for (unsigned i = 0, e = DelayedDestructorExceptionSpecChecks.size(); +       i != e; ++i) { +    const CXXDestructorDecl *Dtor = +        DelayedDestructorExceptionSpecChecks[i].first; +    assert(!Dtor->getParent()->isDependentType() && +           "Should not ever add destructors of templates into the list."); +    CheckOverridingFunctionExceptionSpec(Dtor, +        DelayedDestructorExceptionSpecChecks[i].second); +  } +  DelayedDestructorExceptionSpecChecks.clear(); +} +  void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *classDecl, -                                         CXXDestructorDecl *destructor) { +                                         CXXDestructorDecl *destructor, +                                         bool WasDelayed) {    // 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()) +  if (!WasDelayed && dtorType->hasExceptionSpec())      return;    ImplicitExceptionSpecification exceptSpec = @@ -7344,6 +7371,14 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *classDecl,    destructor->setType(ty); +  // If we can't compute the exception specification for this destructor yet +  // (because it depends on an exception specification which we have not parsed +  // yet), make a note that we need to try again when the class is complete. +  if (epi.ExceptionSpecType == EST_Delayed) { +    assert(!WasDelayed && "couldn't compute destructor exception spec"); +    DelayedDestructorExceptionSpecs.push_back(destructor); +  } +    // 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. @@ -7579,8 +7614,9 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(      assert(!Base->getType()->isDependentType() &&             "Cannot generate implicit members for class with dependent bases.");      CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl(); -    LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, false, 0, -                            &HasConstCopyAssignment); +    HasConstCopyAssignment &= +      (bool)LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, +                                    false, 0);    }    // In C++11, the above citation has "or virtual" added @@ -7591,8 +7627,9 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(        assert(!Base->getType()->isDependentType() &&               "Cannot generate implicit members for class with dependent bases.");        CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl(); -      LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, false, 0, -                              &HasConstCopyAssignment); +      HasConstCopyAssignment &= +        (bool)LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, +                                      false, 0);      }    } @@ -7606,8 +7643,9 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(         ++Field) {      QualType FieldType = Context.getBaseElementType((*Field)->getType());      if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { -      LookupCopyingAssignment(FieldClassDecl, Qualifiers::Const, false, 0, -                              &HasConstCopyAssignment); +      HasConstCopyAssignment &= +        (bool)LookupCopyingAssignment(FieldClassDecl, Qualifiers::Const, +                                      false, 0);      }    } @@ -8610,8 +8648,8 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {      CXXRecordDecl *BaseClassDecl        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); -    LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const, -                             &HasConstCopyConstructor); +    HasConstCopyConstructor &= +      (bool)LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const);    }    for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), @@ -8620,8 +8658,8 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {         ++Base) {      CXXRecordDecl *BaseClassDecl        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); -    LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const, -                             &HasConstCopyConstructor); +    HasConstCopyConstructor &= +      (bool)LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const);    }    //     -- for all the nonstatic data members of X that are of a @@ -8634,8 +8672,8 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {         ++Field) {      QualType FieldType = Context.getBaseElementType((*Field)->getType());      if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { -      LookupCopyingConstructor(FieldClassDecl, Qualifiers::Const, -                               &HasConstCopyConstructor); +      HasConstCopyConstructor &= +        (bool)LookupCopyingConstructor(FieldClassDecl, Qualifiers::Const);      }    }    //   Otherwise, the implicitly declared copy constructor will have @@ -11260,66 +11298,6 @@ Sema::checkExceptionSpecification(ExceptionSpecificationType EST,    }  } -void Sema::actOnDelayedExceptionSpecification(Decl *MethodD, -             ExceptionSpecificationType EST, -             SourceRange SpecificationRange, -             ArrayRef<ParsedType> DynamicExceptions, -             ArrayRef<SourceRange> DynamicExceptionRanges, -             Expr *NoexceptExpr) { -  if (!MethodD) -    return; -   -  // Dig out the method we're referring to. -  CXXMethodDecl *Method = 0; -  if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(MethodD)) -    Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); -  else -    Method = dyn_cast<CXXMethodDecl>(MethodD); -   -  if (!Method) -    return; -   -  // Dig out the prototype. This should never fail. -  const FunctionProtoType *Proto -    = dyn_cast<FunctionProtoType>(Method->getType()); -  if (!Proto) -    return; -   -  // Check the exception specification. -  llvm::SmallVector<QualType, 4> Exceptions; -  FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); -  checkExceptionSpecification(EST, DynamicExceptions, DynamicExceptionRanges, -                              NoexceptExpr, Exceptions, EPI); -   -  // Rebuild the function type. -  QualType T = Context.getFunctionType(Proto->getResultType(), -                                       Proto->arg_type_begin(), -                                       Proto->getNumArgs(), -                                       EPI); -  if (TypeSourceInfo *TSInfo = Method->getTypeSourceInfo()) { -    // FIXME: When we get proper type location information for exceptions, -    // we'll also have to rebuild the TypeSourceInfo. For now, we just patch -    // up the TypeSourceInfo; -    assert(TypeLoc::getFullDataSizeForType(T) -             == TypeLoc::getFullDataSizeForType(Method->getType()) && -           "TypeLoc size mismatch with delayed exception specification"); -    TSInfo->overrideType(T); -  } - -  Method->setType(T); -   -  if (Method->isStatic()) -    checkThisInStaticMemberFunctionExceptionSpec(Method); -   -  if (Method->isVirtual()) { -    // Check overrides, which we previously had to delay. -    for (CXXMethodDecl::method_iterator O = Method->begin_overridden_methods(), -                                     OEnd = Method->end_overridden_methods(); -         O != OEnd; ++O) -      CheckOverridingFunctionExceptionSpec(Method, *O); -  } -} -  /// IdentifyCUDATarget - Determine the CUDA compilation target for this function  Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {    // Implicitly declared functions (e.g. copy constructors) are diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index f003bddc05bbd..9f5138ba4a40b 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -2277,7 +2277,7 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,      Result->setMethod(DD);      Result->setKind(DD->isDeleted() ?                      SpecialMemberOverloadResult::NoMemberOrDeleted : -                    SpecialMemberOverloadResult::SuccessNonConst); +                    SpecialMemberOverloadResult::Success);      return Result;    } @@ -2288,6 +2288,9 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,    Expr *Arg = 0;    unsigned NumArgs; +  QualType ArgType = CanTy; +  ExprValueKind VK = VK_LValue; +    if (SM == CXXDefaultConstructor) {      Name = Context.DeclarationNames.getCXXConstructorName(CanTy);      NumArgs = 0; @@ -2308,7 +2311,6 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,          DeclareImplicitMoveAssignment(RD);      } -    QualType ArgType = CanTy;      if (ConstArg)        ArgType.addConst();      if (VolatileArg) @@ -2321,14 +2323,17 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,      // 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 == CXXCopyConstructor || SM == CXXCopyAssignment)        VK = VK_LValue;      else        VK = VK_RValue; +  } +  OpaqueValueExpr FakeArg(SourceLocation(), ArgType, VK); + +  if (SM != CXXDefaultConstructor) {      NumArgs = 1; -    Arg = new (Context) OpaqueValueExpr(SourceLocation(), ArgType, VK); +    Arg = &FakeArg;    }    // Create the object argument @@ -2338,17 +2343,14 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,    if (VolatileThis)      ThisTy.addVolatile();    Expr::Classification Classification = -    (new (Context) OpaqueValueExpr(SourceLocation(), ThisTy, -                                   RValueThis ? VK_RValue : VK_LValue))-> -        Classify(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; -  SpecialMemberOverloadResult::Kind SuccessKind = -      SpecialMemberOverloadResult::SuccessNonConst;    llvm::tie(I, E) = RD->lookup(Name);    assert((I != E) && @@ -2378,17 +2380,6 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,        else          AddOverloadCandidate(M, DeclAccessPair::make(M, AS_public),                               llvm::makeArrayRef(&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->isReferenceType() || -            ArgType->getPointeeType().isConstQualified()) -          SuccessKind = SpecialMemberOverloadResult::SuccessConst; -      }      } else if (FunctionTemplateDecl *Tmpl =                   dyn_cast<FunctionTemplateDecl>(Cand)) {        if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) @@ -2409,7 +2400,7 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,    switch (OCS.BestViableFunction(*this, SourceLocation(), Best)) {      case OR_Success:        Result->setMethod(cast<CXXMethodDecl>(Best->Function)); -      Result->setKind(SuccessKind); +      Result->setKind(SpecialMemberOverloadResult::Success);        break;      case OR_Deleted: @@ -2442,17 +2433,13 @@ CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) {  /// \brief Look up the copying constructor for the given class.  CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class, -                                                   unsigned Quals, -                                                   bool *ConstParamMatch) { +                                                   unsigned Quals) {    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());  } @@ -2485,8 +2472,7 @@ DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {  /// \brief Look up the copying assignment operator for the given class.  CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class,                                               unsigned Quals, bool RValueThis, -                                             unsigned ThisQuals, -                                             bool *ConstParamMatch) { +                                             unsigned ThisQuals) {    assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) &&           "non-const, non-volatile qualifiers for copy assignment arg");    assert(!(ThisQuals & ~(Qualifiers::Const | Qualifiers::Volatile)) && @@ -2497,9 +2483,6 @@ CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class,                          ThisQuals & Qualifiers::Const,                          ThisQuals & Qualifiers::Volatile); -  if (ConstParamMatch) -    *ConstParamMatch = Result->hasConstParamMatch(); -    return Result->getMethod();  } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index d0906ded0cbbb..1400e7e5c4199 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -561,7 +561,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,                               /*const qualifier*/SourceLocation(),                               /*volatile qualifier*/SourceLocation(),                               /*mutable qualifier*/SourceLocation(), -                             /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0, 0, +                             /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0,                               /*parens*/ loc, loc,                               declarator)); @@ -4195,7 +4195,8 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,    // class template specialization, or an array with known size of such,    // try to instantiate it.    QualType MaybeTemplate = T; -  if (const ConstantArrayType *Array = Context.getAsConstantArrayType(T)) +  while (const ConstantArrayType *Array +           = Context.getAsConstantArrayType(MaybeTemplate))      MaybeTemplate = Array->getElementType();    if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {      if (ClassTemplateSpecializationDecl *ClassTemplateSpec diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 06b42f3ab1309..fd0c17139468b 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -3866,6 +3866,9 @@ QualType ASTReader::readTypeRecord(unsigned Index) {        EPI.Exceptions = Exceptions.data();      } else if (EST == EST_ComputedNoexcept) {        EPI.NoexceptExpr = ReadExpr(*Loc.F); +    } else if (EST == EST_Uninstantiated) { +      EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx); +      EPI.ExceptionSpecTemplate = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);      }      return Context.getFunctionType(ResultType, ParamTypes.data(), NumParams,                                      EPI); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 81c0a9dd48acd..36933a9d9b8c6 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -195,6 +195,9 @@ void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {        Writer.AddTypeRef(T->getExceptionType(I), Record);    } else if (T->getExceptionSpecType() == EST_ComputedNoexcept) {      Writer.AddStmt(T->getNoexceptExpr()); +  } else if (T->getExceptionSpecType() == EST_Uninstantiated) { +    Writer.AddDeclRef(T->getExceptionSpecDecl(), Record); +    Writer.AddDeclRef(T->getExceptionSpecTemplate(), Record);    }    Code = TYPE_FUNCTION_PROTO;  } diff --git a/test/CXX/class/class.mem/p2.cpp b/test/CXX/class/class.mem/p2.cpp index 0a823f4c1f00c..4aa4a5c6f1b7b 100644 --- a/test/CXX/class/class.mem/p2.cpp +++ b/test/CXX/class/class.mem/p2.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s  +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s  // C++11 [class.mem]p2:  //   A class is considered a completely-defined object type (or diff --git a/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp b/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp index ad4f4064c2552..030c90c525c0e 100644 --- a/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp @@ -91,10 +91,11 @@ namespace Static {  namespace PR12564 {    struct Base { -    void bar(Base&) {} +    void bar(Base&) {} // unexpected-note {{here}}    };    struct Derived : Base { -    void foo(Derived& d) noexcept(noexcept(d.bar(d))) {} +    // FIXME: This should be accepted. +    void foo(Derived& d) noexcept(noexcept(d.bar(d))) {} // unexpected-error {{cannot bind to a value of unrelated type}}    };  } diff --git a/test/CXX/special/class.copy/implicit-move.cpp b/test/CXX/special/class.copy/implicit-move.cpp index b1b298e893ff2..3e9accfbf6a72 100644 --- a/test/CXX/special/class.copy/implicit-move.cpp +++ b/test/CXX/special/class.copy/implicit-move.cpp @@ -198,15 +198,15 @@ namespace DR1402 {    struct NoMove4 : NonTrivialCopyAssign {}; // expected-note 2{{'const DR1402::NoMove4 &'}}    struct NoMove5 : virtual NonTrivialCopyCtor {}; // expected-note 2{{'const DR1402::NoMove5 &'}}    struct NoMove6 : virtual NonTrivialCopyAssign {}; // expected-note 2{{'const DR1402::NoMove6 &'}} -  struct NoMove7 : NonTrivialCopyCtorVBase {}; // expected-note 2{{'DR1402::NoMove7 &'}} -  struct NoMove8 : NonTrivialCopyAssignVBase {}; // expected-note 2{{'DR1402::NoMove8 &'}} +  struct NoMove7 : NonTrivialCopyCtorVBase {}; // expected-note 2{{'const DR1402::NoMove7 &'}} +  struct NoMove8 : NonTrivialCopyAssignVBase {}; // expected-note 2{{'const DR1402::NoMove8 &'}}    // A non-trivially-move-assignable virtual base class inhibits the declaration    // of a move assignment (which might move-assign the base class multiple    // times).    struct NoMove9 : NonTrivialMoveAssign {}; -  struct NoMove10 : virtual NonTrivialMoveAssign {}; // expected-note {{'DR1402::NoMove10 &'}} -  struct NoMove11 : NonTrivialMoveAssignVBase {}; // expected-note {{'DR1402::NoMove11 &'}} +  struct NoMove10 : virtual NonTrivialMoveAssign {}; // expected-note {{'const DR1402::NoMove10 &'}} +  struct NoMove11 : NonTrivialMoveAssignVBase {}; // expected-note {{'const DR1402::NoMove11 &'}}    struct Test {      friend NoMove1::NoMove1(NoMove1 &&); // expected-error {{no matching function}} diff --git a/test/CXX/special/class.copy/p8-cxx11.cpp b/test/CXX/special/class.copy/p8-cxx11.cpp new file mode 100644 index 0000000000000..02e6cd1c9ab6c --- /dev/null +++ b/test/CXX/special/class.copy/p8-cxx11.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +// C++98 [class.copy]p5 / C++11 [class.copy]p8. + +// The implicitly-declared copy constructor for a class X will have the form +//   X::X(const X&) +// if [every direct subobject] has a copy constructor whose first parameter is +// of type 'const volatile[opt] T &'. Otherwise, it will have the form +//   X::X(X&) + +struct ConstCopy { +  ConstCopy(const ConstCopy &); +}; + +struct NonConstCopy { +  NonConstCopy(NonConstCopy &); +}; + +struct DeletedConstCopy { +  DeletedConstCopy(const DeletedConstCopy &) = delete; +}; + +struct DeletedNonConstCopy { +  DeletedNonConstCopy(DeletedNonConstCopy &) = delete; +}; + +struct ImplicitlyDeletedConstCopy { +  ImplicitlyDeletedConstCopy(ImplicitlyDeletedConstCopy &&); +}; + + +struct A : ConstCopy {}; +struct B : NonConstCopy { ConstCopy a; }; +struct C : ConstCopy { NonConstCopy a; }; +struct D : DeletedConstCopy {}; +struct E : DeletedNonConstCopy {}; +struct F { ImplicitlyDeletedConstCopy a; }; +struct G : virtual B {}; + +struct Test { +  friend A::A(const A &); +  friend B::B(B &); +  friend C::C(C &); +  friend D::D(const D &); +  friend E::E(E &); +  friend F::F(const F &); +  friend G::G(G &); +}; diff --git a/test/CodeGenCXX/x86-64-abi-sret-vs-2word-struct-param.cpp b/test/CodeGenCXX/x86-64-abi-sret-vs-2word-struct-param.cpp deleted file mode 100644 index 1aa80f2d6e6f6..0000000000000 --- a/test/CodeGenCXX/x86-64-abi-sret-vs-2word-struct-param.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s -// XTARGET: x86 -// PR4242 -// (PR 4242 bug is on 64-bit only, test passes on x86-32 as well) - -struct S { -    void* data[3]; -}; - -struct T { -    void* data[2]; -}; - -// CHECK: %struct.T* byval -extern "C" S fail(int, int, int, int, T t, void* p) { -    S s; -    s.data[0] = t.data[0]; -    s.data[1] = t.data[1]; -    s.data[2] = p; -    return s; -} - -// CHECK: %struct.T* byval -extern "C" S* succeed(S* sret, int, int, int, int, T t, void* p) { -    sret->data[0] = t.data[0]; -    sret->data[1] = t.data[1]; -    sret->data[2] = p; -    return sret; -} diff --git a/test/CodeGenCXX/x86_64-arguments.cpp b/test/CodeGenCXX/x86_64-arguments.cpp index e1d9dfc1fc308..672180363fcac 100644 --- a/test/CodeGenCXX/x86_64-arguments.cpp +++ b/test/CodeGenCXX/x86_64-arguments.cpp @@ -56,6 +56,7 @@ namespace PR7742 { // Also rdar://8250764    // CHECK: define <2 x float> @_ZN6PR77423fooEPNS_2c2E(%"struct.PR7742::c2"* %P)    c2 foo(c2 *P) { +    return c2();    }  } @@ -149,3 +150,34 @@ namespace test8 {     foo(b);    }  } + +// PR4242 +namespace test9 { +  // Large enough to be passed indirectly. +  struct S { void *data[3]; }; + +  struct T { void *data[2]; }; + +  // CHECK: define void @_ZN5test93fooEPNS_1SEPNS_1TE([[S:%.*]]*, [[T:%.*]]*) +  void foo(S*, T*) {} + +  // CHECK: define void @_ZN5test91aEiiiiNS_1TEPv([[S]]* noalias sret {{%.*}}, i32, i32, i32, i32, [[T]]* byval align 8, i8*) +  S a(int, int, int, int, T, void*) { +    return S(); +  } + +  // CHECK: define [[S]]* @_ZN5test91bEPNS_1SEiiiiNS_1TEPv([[S]]* {{%.*}}, i32, i32, i32, i32, [[T:%.*]]* byval align 8, i8*) +  S* b(S* sret, int, int, int, int, T, void*) { +    return sret; +  } + +  // CHECK: define void @_ZN5test91cEiiiNS_1TEPv([[S]]* noalias sret {{%.*}}, i32, i32, i32, i8* {{%.*}}, i8* {{%.*}}, i8*) +  S c(int, int, int, T, void*) { +    return S(); +  } + +  // CHECK: define [[S]]* @_ZN5test91dEPNS_1SEiiiNS_1TEPv([[S]]* {{%.*}}, i32, i32, i32, i8* {{%.*}}, i8* {{%.*}}, i8*) +  S* d(S* sret, int, int, int, T, void*) { +    return sret; +  } +} diff --git a/test/PCH/cxx11-exception-spec.cpp b/test/PCH/cxx11-exception-spec.cpp new file mode 100644 index 0000000000000..3fca4e48acf8f --- /dev/null +++ b/test/PCH/cxx11-exception-spec.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch %s -o %t +// RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t -verify %s + +#ifndef HEADER_INCLUDED + +#define HEADER_INCLUDED + +template<bool b> int f() noexcept(b) {} +decltype(f<false>()) a; +decltype(f<true>()) b; + +#else + +static_assert(!noexcept(f<false>()), ""); +static_assert(noexcept(f<true>()), ""); + +#endif diff --git a/test/Parser/recursion-limits.cpp b/test/Parser/recursion-limits.cpp new file mode 100644 index 0000000000000..ea25dea0daccc --- /dev/null +++ b/test/Parser/recursion-limits.cpp @@ -0,0 +1,259 @@ +// RUN: %clang_cc1 -fsyntax-only %s -verify +class outer { +  class inner1 { inner1(); }; +  class inner2 { inner2(); }; +  class inner3 { inner3(); }; +  class inner4 { inner4(); }; +  class inner5 { inner5(); }; +  class inner6 { inner6(); }; +  class inner7 { inner7(); }; +  class inner8 { inner8(); }; +  class inner9 { inner9(); }; +  class inner10 { inner10(); }; +  class inner11 { inner11(); }; +  class inner12 { inner12(); }; +  class inner13 { inner13(); }; +  class inner14 { inner14(); }; +  class inner15 { inner15(); }; +  class inner16 { inner16(); }; +  class inner17 { inner17(); }; +  class inner18 { inner18(); }; +  class inner19 { inner19(); }; +  class inner20 { inner20(); }; +  class inner21 { inner21(); }; +  class inner22 { inner22(); }; +  class inner23 { inner23(); }; +  class inner24 { inner24(); }; +  class inner25 { inner25(); }; +  class inner26 { inner26(); }; +  class inner27 { inner27(); }; +  class inner28 { inner28(); }; +  class inner29 { inner29(); }; +  class inner30 { inner30(); }; +  class inner31 { inner31(); }; +  class inner32 { inner32(); }; +  class inner33 { inner33(); }; +  class inner34 { inner34(); }; +  class inner35 { inner35(); }; +  class inner36 { inner36(); }; +  class inner37 { inner37(); }; +  class inner38 { inner38(); }; +  class inner39 { inner39(); }; +  class inner40 { inner40(); }; +  class inner41 { inner41(); }; +  class inner42 { inner42(); }; +  class inner43 { inner43(); }; +  class inner44 { inner44(); }; +  class inner45 { inner45(); }; +  class inner46 { inner46(); }; +  class inner47 { inner47(); }; +  class inner48 { inner48(); }; +  class inner49 { inner49(); }; +  class inner50 { inner50(); }; +  class inner51 { inner51(); }; +  class inner52 { inner52(); }; +  class inner53 { inner53(); }; +  class inner54 { inner54(); }; +  class inner55 { inner55(); }; +  class inner56 { inner56(); }; +  class inner57 { inner57(); }; +  class inner58 { inner58(); }; +  class inner59 { inner59(); }; +  class inner60 { inner60(); }; +  class inner61 { inner61(); }; +  class inner62 { inner62(); }; +  class inner63 { inner63(); }; +  class inner64 { inner64(); }; +  class inner65 { inner65(); }; +  class inner66 { inner66(); }; +  class inner67 { inner67(); }; +  class inner68 { inner68(); }; +  class inner69 { inner69(); }; +  class inner70 { inner70(); }; +  class inner71 { inner71(); }; +  class inner72 { inner72(); }; +  class inner73 { inner73(); }; +  class inner74 { inner74(); }; +  class inner75 { inner75(); }; +  class inner76 { inner76(); }; +  class inner77 { inner77(); }; +  class inner78 { inner78(); }; +  class inner79 { inner79(); }; +  class inner80 { inner80(); }; +  class inner81 { inner81(); }; +  class inner82 { inner82(); }; +  class inner83 { inner83(); }; +  class inner84 { inner84(); }; +  class inner85 { inner85(); }; +  class inner86 { inner86(); }; +  class inner87 { inner87(); }; +  class inner88 { inner88(); }; +  class inner89 { inner89(); }; +  class inner90 { inner90(); }; +  class inner91 { inner91(); }; +  class inner92 { inner92(); }; +  class inner93 { inner93(); }; +  class inner94 { inner94(); }; +  class inner95 { inner95(); }; +  class inner96 { inner96(); }; +  class inner97 { inner97(); }; +  class inner98 { inner98(); }; +  class inner99 { inner99(); }; +  class inner100 { inner100(); }; +  class inner101 { inner101(); }; +  class inner102 { inner102(); }; +  class inner103 { inner103(); }; +  class inner104 { inner104(); }; +  class inner105 { inner105(); }; +  class inner106 { inner106(); }; +  class inner107 { inner107(); }; +  class inner108 { inner108(); }; +  class inner109 { inner109(); }; +  class inner110 { inner110(); }; +  class inner111 { inner111(); }; +  class inner112 { inner112(); }; +  class inner113 { inner113(); }; +  class inner114 { inner114(); }; +  class inner115 { inner115(); }; +  class inner116 { inner116(); }; +  class inner117 { inner117(); }; +  class inner118 { inner118(); }; +  class inner119 { inner119(); }; +  class inner120 { inner120(); }; +  class inner121 { inner121(); }; +  class inner122 { inner122(); }; +  class inner123 { inner123(); }; +  class inner124 { inner124(); }; +  class inner125 { inner125(); }; +  class inner126 { inner126(); }; +  class inner127 { inner127(); }; +  class inner128 { inner128(); }; +  class inner129 { inner129(); }; +  class inner130 { inner130(); }; +  class inner131 { inner131(); }; +  class inner132 { inner132(); }; +  class inner133 { inner133(); }; +  class inner134 { inner134(); }; +  class inner135 { inner135(); }; +  class inner136 { inner136(); }; +  class inner137 { inner137(); }; +  class inner138 { inner138(); }; +  class inner139 { inner139(); }; +  class inner140 { inner140(); }; +  class inner141 { inner141(); }; +  class inner142 { inner142(); }; +  class inner143 { inner143(); }; +  class inner144 { inner144(); }; +  class inner145 { inner145(); }; +  class inner146 { inner146(); }; +  class inner147 { inner147(); }; +  class inner148 { inner148(); }; +  class inner149 { inner149(); }; +  class inner150 { inner150(); }; +  class inner151 { inner151(); }; +  class inner152 { inner152(); }; +  class inner153 { inner153(); }; +  class inner154 { inner154(); }; +  class inner155 { inner155(); }; +  class inner156 { inner156(); }; +  class inner157 { inner157(); }; +  class inner158 { inner158(); }; +  class inner159 { inner159(); }; +  class inner160 { inner160(); }; +  class inner161 { inner161(); }; +  class inner162 { inner162(); }; +  class inner163 { inner163(); }; +  class inner164 { inner164(); }; +  class inner165 { inner165(); }; +  class inner166 { inner166(); }; +  class inner167 { inner167(); }; +  class inner168 { inner168(); }; +  class inner169 { inner169(); }; +  class inner170 { inner170(); }; +  class inner171 { inner171(); }; +  class inner172 { inner172(); }; +  class inner173 { inner173(); }; +  class inner174 { inner174(); }; +  class inner175 { inner175(); }; +  class inner176 { inner176(); }; +  class inner177 { inner177(); }; +  class inner178 { inner178(); }; +  class inner179 { inner179(); }; +  class inner180 { inner180(); }; +  class inner181 { inner181(); }; +  class inner182 { inner182(); }; +  class inner183 { inner183(); }; +  class inner184 { inner184(); }; +  class inner185 { inner185(); }; +  class inner186 { inner186(); }; +  class inner187 { inner187(); }; +  class inner188 { inner188(); }; +  class inner189 { inner189(); }; +  class inner190 { inner190(); }; +  class inner191 { inner191(); }; +  class inner192 { inner192(); }; +  class inner193 { inner193(); }; +  class inner194 { inner194(); }; +  class inner195 { inner195(); }; +  class inner196 { inner196(); }; +  class inner197 { inner197(); }; +  class inner198 { inner198(); }; +  class inner199 { inner199(); }; +  class inner200 { inner200(); }; +  class inner201 { inner201(); }; +  class inner202 { inner202(); }; +  class inner203 { inner203(); }; +  class inner204 { inner204(); }; +  class inner205 { inner205(); }; +  class inner206 { inner206(); }; +  class inner207 { inner207(); }; +  class inner208 { inner208(); }; +  class inner209 { inner209(); }; +  class inner210 { inner210(); }; +  class inner211 { inner211(); }; +  class inner212 { inner212(); }; +  class inner213 { inner213(); }; +  class inner214 { inner214(); }; +  class inner215 { inner215(); }; +  class inner216 { inner216(); }; +  class inner217 { inner217(); }; +  class inner218 { inner218(); }; +  class inner219 { inner219(); }; +  class inner220 { inner220(); }; +  class inner221 { inner221(); }; +  class inner222 { inner222(); }; +  class inner223 { inner223(); }; +  class inner224 { inner224(); }; +  class inner225 { inner225(); }; +  class inner226 { inner226(); }; +  class inner227 { inner227(); }; +  class inner228 { inner228(); }; +  class inner229 { inner229(); }; +  class inner230 { inner230(); }; +  class inner231 { inner231(); }; +  class inner232 { inner232(); }; +  class inner233 { inner233(); }; +  class inner234 { inner234(); }; +  class inner235 { inner235(); }; +  class inner236 { inner236(); }; +  class inner237 { inner237(); }; +  class inner238 { inner238(); }; +  class inner239 { inner239(); }; +  class inner240 { inner240(); }; +  class inner241 { inner241(); }; +  class inner242 { inner242(); }; +  class inner243 { inner243(); }; +  class inner244 { inner244(); }; +  class inner245 { inner245(); }; +  class inner246 { inner246(); }; +  class inner247 { inner247(); }; +  class inner248 { inner248(); }; +  class inner249 { inner249(); }; +  class inner250 { inner250(); }; +  class inner251 { inner251(); }; +  class inner252 { inner252(); }; +  class inner253 { inner253(); }; +  class inner254 { inner254(); }; +  class inner255 { inner255(); }; +  class inner256 { inner256(); }; +}; diff --git a/test/Rewriter/rewrite-modern-extern-c-func-decl.mm b/test/Rewriter/rewrite-modern-extern-c-func-decl.mm index 10023bbc9f9fb..82d5a4d9c34e9 100644 --- a/test/Rewriter/rewrite-modern-extern-c-func-decl.mm +++ b/test/Rewriter/rewrite-modern-extern-c-func-decl.mm @@ -1,10 +1,7 @@ -// RUN: %clang_cc1 -fms-extensions -rewrite-objc -x objective-c++ -fblocks -o %t-rw.cpp %s -// RUN: %clang_cc1 -fsyntax-only -Werror -Wno-address-of-temporary -Wno-attributes -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp +// RUN: %clang_cc1 -fms-extensions -U__declspec -rewrite-objc -x objective-c++ -fblocks -o %t-rw.cpp %s +// RUN: %clang_cc1 -fsyntax-only -Werror -Wno-address-of-temporary -Wno-attributes -D"Class=void*" -D"id=void*" -D"SEL=void*" -U__declspec -D"__declspec(X)=" %t-rw.cpp  // rdar://11131490 -// XFAIL: mingw -// FIXME: __declspec(X) is predefined on mingw. -  extern "C" __declspec(dllexport) void BreakTheRewriter(void) {          __block int aBlockVariable = 0;          void (^aBlock)(void) = ^ { diff --git a/test/SemaCXX/cxx0x-initializer-references.cpp b/test/SemaCXX/cxx0x-initializer-references.cpp index d8fdd5a5a07a5..c4e9c907a37a3 100644 --- a/test/SemaCXX/cxx0x-initializer-references.cpp +++ b/test/SemaCXX/cxx0x-initializer-references.cpp @@ -85,3 +85,8 @@ namespace PR12182 {        f({1, 2});    }  } + +namespace PR12660 { +  const int &i { 1 }; +  struct S { S(int); } const &s { 2 }; +} diff --git a/test/SemaCXX/dependent-noexcept-unevaluated.cpp b/test/SemaCXX/dependent-noexcept-unevaluated.cpp index fad8d0918d530..0a3a8bb250bc5 100644 --- a/test/SemaCXX/dependent-noexcept-unevaluated.cpp +++ b/test/SemaCXX/dependent-noexcept-unevaluated.cpp @@ -23,7 +23,7 @@ struct array  {      T data[N]; -  void swap(array& a) noexcept(noexcept(::swap(declval<T&>(), declval<T&>()))); +    void swap(array& a) noexcept(noexcept(swap(declval<T&>(), declval<T&>())));  };  struct DefaultOnly @@ -38,4 +38,3 @@ int main()  {      array<DefaultOnly, 1> a, b;  } - diff --git a/test/SemaCXX/implicit-exception-spec.cpp b/test/SemaCXX/implicit-exception-spec.cpp index 143d9f7cc877a..25316f8d51ee5 100644 --- a/test/SemaCXX/implicit-exception-spec.cpp +++ b/test/SemaCXX/implicit-exception-spec.cpp @@ -40,9 +40,12 @@ namespace InClassInitializers {  }  namespace ExceptionSpecification { -  struct Nested { +  // A type is permitted to be used in a dynamic exception specification when it +  // is still being defined, but isn't complete within such an exception +  // specification. +  struct Nested { // expected-note {{not complete}}      struct T { -      T() noexcept(!noexcept(Nested())); // expected-error{{exception specification is not available until end of class definition}} +      T() noexcept(!noexcept(Nested())); // expected-error{{incomplete type}}      } t;    };  } @@ -54,3 +57,33 @@ namespace DefaultArgument {      } t; // expected-note {{has no default constructor}}    };  } + +namespace ImplicitDtorExceptionSpec { +  struct A { +    virtual ~A(); + +    struct Inner { +      ~Inner() throw(); +    }; +    Inner inner; +  }; + +  struct B { +    virtual ~B() {} // expected-note {{here}} +  }; + +  struct C : B { +    virtual ~C() {} +    A a; +  }; + +  struct D : B { +    ~D(); // expected-error {{more lax than base}} +    struct E { +      ~E(); +      struct F { +        ~F() throw(A); +      } f; +    } e; +  }; +} diff --git a/test/SemaObjCXX/ivar-construct.mm b/test/SemaObjCXX/ivar-construct.mm index 535d2a0217ff7..a066fca3595a2 100644 --- a/test/SemaObjCXX/ivar-construct.mm +++ b/test/SemaObjCXX/ivar-construct.mm @@ -27,3 +27,11 @@ struct Z; // expected-note{{forward declaration}}  @implementation B  @end + +// <rdar://problem/11284902> +template<typename T> struct Incomplete; // expected-note{{declared here}} + +@interface C { +  Incomplete<int> a[4][4][4]; // expected-error{{implicit instantiation of undefined template 'Incomplete<int>'}} +} +@end  | 
