diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2012-05-22 21:36:38 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2012-05-22 21:36:38 +0000 |
commit | e51da3eab6ad2d02fcd8f68bdaef22d33a855210 (patch) | |
tree | 1bfa44f5a9427d658426ac7786a70741e36d1bc8 | |
parent | 6b9a6e390fbb92c40eb9c6ac9e7abbd88dd7a767 (diff) |
Notes
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 |