Author: abataev Date: Wed Jun 15 06:19:39 2016 New Revision: 272774 URL: http://llvm.org/viewvc/llvm-project?rev=272774&view=rev Log: [MSVC] Late parsing of in-class defined member functions in template classes.
MSVC actively uses unqualified lookup in dependent bases, lookup at the instantiation point (non-dependent names may be resolved on things declared later) etc. and all this stuff is the main cause of incompatibility between clang and MSVC. Clang tries to emulate MSVC behavior but it may fail in many cases. clang could store lexed tokens for member functions definitions within ClassTemplateDecl for later parsing during template instantiation. It will allow resolving many possible issues with lookup in dependent base classes and removing many already existing MSVC-specific hacks/workarounds from the clang code. Modified: cfe/trunk/include/clang-c/Index.h cfe/trunk/include/clang/AST/RecursiveASTVisitor.h cfe/trunk/include/clang/AST/StmtCXX.h cfe/trunk/include/clang/Basic/StmtNodes.td cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/include/clang/Serialization/ASTBitCodes.h cfe/trunk/lib/AST/StmtCXX.cpp cfe/trunk/lib/AST/StmtPrinter.cpp cfe/trunk/lib/AST/StmtProfile.cpp cfe/trunk/lib/CodeGen/CGStmt.cpp cfe/trunk/lib/Parse/ParseTemplate.cpp cfe/trunk/lib/Parse/Parser.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/lib/Sema/SemaStmt.cpp cfe/trunk/lib/Sema/TreeTransform.h cfe/trunk/lib/Serialization/ASTReaderStmt.cpp cfe/trunk/lib/Serialization/ASTWriterStmt.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp cfe/trunk/tools/libclang/CIndex.cpp cfe/trunk/tools/libclang/CXCursor.cpp Modified: cfe/trunk/include/clang-c/Index.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/include/clang-c/Index.h (original) +++ cfe/trunk/include/clang-c/Index.h Wed Jun 15 06:19:39 2016 @@ -2305,7 +2305,11 @@ enum CXCursorKind { */ CXCursor_OMPTargetUpdateDirective = 265, - CXCursor_LastStmt = CXCursor_OMPTargetUpdateDirective, + /** \brief A MS-specific late parsed compound statement. + */ + CXCursor_MSLateParsedCompoundStmt = 266, + + CXCursor_LastStmt = CXCursor_MSLateParsedCompoundStmt, /** * \brief Cursor that represents the translation unit itself. Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original) +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Wed Jun 15 06:19:39 2016 @@ -2332,6 +2332,7 @@ DEF_TRAVERSE_STMT(SEHExceptStmt, {}) DEF_TRAVERSE_STMT(SEHFinallyStmt, {}) DEF_TRAVERSE_STMT(SEHLeaveStmt, {}) DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); }) +DEF_TRAVERSE_STMT(MSLateParsedCompoundStmt, {}) DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {}) DEF_TRAVERSE_STMT(OpaqueValueExpr, {}) Modified: cfe/trunk/include/clang/AST/StmtCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtCXX.h?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/StmtCXX.h (original) +++ cfe/trunk/include/clang/AST/StmtCXX.h Wed Jun 15 06:19:39 2016 @@ -18,6 +18,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Stmt.h" +#include "clang/Lex/Token.h" #include "llvm/Support/Compiler.h" namespace clang { @@ -417,6 +418,51 @@ public: } }; +/// This represents a group of statements like { stmt stmt } that must be parsed +/// only during instantiation. Required for better MSVC compatibility. +class MSLateParsedCompoundStmt final + : public Stmt, + private llvm::TrailingObjects<MSLateParsedCompoundStmt, Token> { + friend class TrailingObjects; + friend class ASTStmtReader; + SourceLocation LBraceLoc, RBraceLoc; + StringRef StringRep; + unsigned NumToks; + + MSLateParsedCompoundStmt() + : Stmt(MSLateParsedCompoundStmtClass), NumToks(0) {} + + /// Set tokens for the statement. + void init(ASTContext &C, SourceLocation LB, SourceLocation RB, + ArrayRef<Token> Tokens, StringRef Rep); + +public: + static MSLateParsedCompoundStmt *Create(ASTContext &C, SourceLocation LB, + SourceLocation RB, + ArrayRef<Token> Tokens, + StringRef Rep); + /// Build an empty statement. + static MSLateParsedCompoundStmt *CreateEmpty(ASTContext &C, + unsigned NumTokens); + + SourceLocation getLocStart() const LLVM_READONLY { return LBraceLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RBraceLoc; } + + /// Returns representation of the statement as a string. + StringRef getStringRepresentation() const { return StringRep; } + + /// Get list of tokens associated with the statement. + ArrayRef<Token> tokens() const; + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + static bool classof(const Stmt *S) { + return S->getStmtClass() == MSLateParsedCompoundStmtClass; + } +}; + } // end namespace clang #endif Modified: cfe/trunk/include/clang/Basic/StmtNodes.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/StmtNodes.td (original) +++ cfe/trunk/include/clang/Basic/StmtNodes.td Wed Jun 15 06:19:39 2016 @@ -187,6 +187,7 @@ def SEHExceptStmt : Stmt; def SEHFinallyStmt : Stmt; def SEHLeaveStmt : Stmt; def MSDependentExistsStmt : Stmt; +def MSLateParsedCompoundStmt : Stmt; // OpenCL Extensions. def AsTypeExpr : DStmt<Expr>; Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Wed Jun 15 06:19:39 2016 @@ -1181,9 +1181,11 @@ private: void LexTemplateFunctionForLateParsing(CachedTokens &Toks); void ParseLateTemplatedFuncDef(LateParsedTemplate &LPT); + void ParseMSVCTemplatedFuncDef(LateParsedTemplate &LPT); static void LateTemplateParserCallback(void *P, LateParsedTemplate &LPT); static void LateTemplateParserCleanupCallback(void *P); + static void MSVCTemplateParserCallback(void *P, LateParsedTemplate &LPT); Sema::ParsingClassState PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass, bool IsInterface); Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Wed Jun 15 06:19:39 2016 @@ -3507,6 +3507,11 @@ public: LabelDecl *GetOrCreateMSAsmLabel(StringRef ExternalLabelName, SourceLocation Location, bool AlwaysCreate); + /// Builds late parsed compound statement or just compound statement in MSVC + /// compatibility mode. + StmtResult ActOnMSLateParsedCompoundStmt(SourceLocation LB, SourceLocation RB, + ArrayRef<Token> Tokens, + StringRef Rep); VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, SourceLocation StartLoc, Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original) +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Wed Jun 15 06:19:39 2016 @@ -1220,6 +1220,8 @@ namespace clang { STMT_GCCASM, /// \brief A MS-style AsmStmt record. STMT_MSASM, + /// \brief A MS-specific late parsed compound statement. + STMT_MS_LATE_PARSED_COMPOUND, /// \brief A PredefinedExpr record. EXPR_PREDEFINED, /// \brief A DeclRefExpr record. Modified: cfe/trunk/lib/AST/StmtCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtCXX.cpp?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/lib/AST/StmtCXX.cpp (original) +++ cfe/trunk/lib/AST/StmtCXX.cpp Wed Jun 15 06:19:39 2016 @@ -86,3 +86,38 @@ VarDecl *CXXForRangeStmt::getLoopVariabl const VarDecl *CXXForRangeStmt::getLoopVariable() const { return const_cast<CXXForRangeStmt *>(this)->getLoopVariable(); } + +MSLateParsedCompoundStmt * +MSLateParsedCompoundStmt::Create(ASTContext &C, SourceLocation LB, + SourceLocation RB, ArrayRef<Token> Tokens, + StringRef Rep) { + // Allocate space for private variables and initializer expressions. + void *Mem = C.Allocate(totalSizeToAlloc<Token>(Tokens.size()), + llvm::alignOf<MSLateParsedCompoundStmt>()); + auto *S = new (Mem) MSLateParsedCompoundStmt(); + S->init(C, LB, RB, Tokens, Rep); + return S; +} + +MSLateParsedCompoundStmt * +MSLateParsedCompoundStmt::CreateEmpty(ASTContext &C, unsigned NumTokens) { + // Allocate space for private variables and initializer expressions. + void *Mem = C.Allocate(totalSizeToAlloc<Token>(NumTokens), + llvm::alignOf<MSLateParsedCompoundStmt>()); + return new (Mem) MSLateParsedCompoundStmt(); +} + +void MSLateParsedCompoundStmt::init(ASTContext &C, SourceLocation LB, + SourceLocation RB, ArrayRef<Token> Tokens, + StringRef Rep) { + LBraceLoc = LB; + RBraceLoc = RB; + std::copy(Tokens.begin(), Tokens.end(), getTrailingObjects<Token>()); + StringRep = Rep.copy(C); + NumToks = Tokens.size(); +} + +ArrayRef<Token> MSLateParsedCompoundStmt::tokens() const { + return llvm::makeArrayRef(getTrailingObjects<Token>(), NumToks); +} + Modified: cfe/trunk/lib/AST/StmtPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/lib/AST/StmtPrinter.cpp (original) +++ cfe/trunk/lib/AST/StmtPrinter.cpp Wed Jun 15 06:19:39 2016 @@ -2352,6 +2352,10 @@ void StmtPrinter::VisitCoreturnStmt(Core OS << ";"; } +void StmtPrinter::VisitMSLateParsedCompoundStmt(MSLateParsedCompoundStmt *S) { + OS << S->getStringRepresentation(); +} + void StmtPrinter::VisitCoawaitExpr(CoawaitExpr *S) { OS << "co_await "; PrintExpr(S->getOperand()); Modified: cfe/trunk/lib/AST/StmtProfile.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/lib/AST/StmtProfile.cpp (original) +++ cfe/trunk/lib/AST/StmtProfile.cpp Wed Jun 15 06:19:39 2016 @@ -1499,6 +1499,11 @@ void StmtProfiler::VisitCoreturnStmt(con VisitStmt(S); } +void StmtProfiler::VisitMSLateParsedCompoundStmt( + const MSLateParsedCompoundStmt *S) { + VisitStmt(S); +} + void StmtProfiler::VisitCoawaitExpr(const CoawaitExpr *S) { VisitExpr(S); } Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGStmt.cpp (original) +++ cfe/trunk/lib/CodeGen/CGStmt.cpp Wed Jun 15 06:19:39 2016 @@ -80,6 +80,7 @@ void CodeGenFunction::EmitStmt(const Stm case Stmt::SEHExceptStmtClass: case Stmt::SEHFinallyStmtClass: case Stmt::MSDependentExistsStmtClass: + case Stmt::MSLateParsedCompoundStmtClass: llvm_unreachable("invalid statement class to emit generically"); case Stmt::NullStmtClass: case Stmt::CompoundStmtClass: Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseTemplate.cpp (original) +++ cfe/trunk/lib/Parse/ParseTemplate.cpp Wed Jun 15 06:19:39 2016 @@ -1417,6 +1417,90 @@ void Parser::ParseLateTemplatedFuncDef(L delete *I; } +void Parser::MSVCTemplateParserCallback(void *P, LateParsedTemplate &LPT) { + ((Parser *)P)->ParseMSVCTemplatedFuncDef(LPT); +} + +/// \brief Late parse a C++ function template in Microsoft mode. +void Parser::ParseMSVCTemplatedFuncDef(LateParsedTemplate &LPT) { + if (!LPT.D) + return; + + // Get the FunctionDecl. + FunctionDecl *FunD = LPT.D->getAsFunction(); + // Track template parameter depth. + TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); + + SmallVector<ParseScope*, 4> TemplateParamScopeStack; + + // Get the list of DeclContexts to reenter. + SmallVector<DeclContext*, 4> DeclContextsToReenter; + DeclContext *DD = FunD; + while (DD && !DD->isTranslationUnit()) { + DeclContextsToReenter.push_back(DD); + DD = DD->getLexicalParent(); + } + + // Reenter template scopes from outermost to innermost. + SmallVectorImpl<DeclContext *>::reverse_iterator II = + DeclContextsToReenter.rbegin(); + for (; II != DeclContextsToReenter.rend(); ++II) { + TemplateParamScopeStack.push_back(new ParseScope(this, + Scope::TemplateParamScope)); + unsigned NumParamLists = + Actions.ActOnReenterTemplateScope(getCurScope(), cast<Decl>(*II)); + CurTemplateDepthTracker.addDepth(NumParamLists); + if (*II != FunD) { + TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope)); + Actions.PushDeclContext(Actions.getCurScope(), *II); + } + } + + assert(!LPT.Toks.empty() && "Empty body!"); + + // Append the current token at the end of the new token stream so that it + // doesn't get lost. + LPT.Toks.push_back(Tok); + PP.EnterTokenStream(LPT.Toks, true); + + // Consume the previously pushed token. + ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); + assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try) && + "Inline method not starting with '{', ':' or 'try'"); + + // Parse the method body. Function body parsing code is similar enough + // to be re-used for method bodies as well. + ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); + + if (Tok.is(tok::kw_try)) { + ParseFunctionTryBlock(LPT.D, FnScope); + } else { + if (Tok.is(tok::colon)) + ParseConstructorInitializer(LPT.D); + else + Actions.ActOnDefaultCtorInitializers(LPT.D); + + if (Tok.is(tok::l_brace)) { + assert((!isa<FunctionTemplateDecl>(LPT.D) || + cast<FunctionTemplateDecl>(LPT.D) + ->getTemplateParameters() + ->getDepth() == TemplateParameterDepth - 1) && + "TemplateParameterDepth should be greater than the depth of " + "current template being instantiated!"); + ParseFunctionStatementBody(LPT.D, FnScope); + Actions.UnmarkAsLateParsedTemplate(FunD); + } else + Actions.ActOnFinishFunctionBody(LPT.D, nullptr); + } + + // Exit scopes. + FnScope.Exit(); + SmallVectorImpl<ParseScope *>::reverse_iterator I = + TemplateParamScopeStack.rbegin(); + for (; I != TemplateParamScopeStack.rend(); ++I) + delete *I; +} + /// \brief Lex a delayed template function for late parsing. void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) { tok::TokenKind kind = Tok.getKind(); Modified: cfe/trunk/lib/Parse/Parser.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/lib/Parse/Parser.cpp (original) +++ cfe/trunk/lib/Parse/Parser.cpp Wed Jun 15 06:19:39 2016 @@ -89,6 +89,8 @@ Parser::Parser(Preprocessor &pp, Sema &a PP.addCommentHandler(CommentSemaHandler.get()); PP.setCodeCompletionHandler(*this); + if (getLangOpts().MSVCCompat) + Actions.SetLateTemplateParser(LateTemplateParserCallback, nullptr, this); } DiagnosticBuilder Parser::Diag(SourceLocation Loc, unsigned DiagID) { @@ -1053,12 +1055,35 @@ Decl *Parser::ParseFunctionDefinition(Pa Actions.MarkAsLateParsedTemplate(FnD, DP, Toks); } return DP; - } - else if (CurParsedObjCImpl && - !TemplateInfo.TemplateParams && - (Tok.is(tok::l_brace) || Tok.is(tok::kw_try) || - Tok.is(tok::colon)) && - Actions.CurContext->isTranslationUnit()) { + } else if (getLangOpts().MSVCCompat && Tok.isNot(tok::equal) && + TemplateInfo.Kind == ParsedTemplateInfo::Template && + Actions.canDelayFunctionBody(D)) { + // In delayed template parsing mode, for function template we consume the + // tokens and store them for late parsing at the end of the translation + // unit. + MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams); + + ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope); + + CachedTokens Toks; + LexTemplateFunctionForLateParsing(Toks); + + Decl *Res = Actions.ActOnStartOfFunctionDef(getCurScope(), D, + *TemplateInfo.TemplateParams); + D.complete(Res); + D.getMutableDeclSpec().abort(); + StmtResult Body = Actions.ActOnMSLateParsedCompoundStmt( + Toks.begin()->getLocation(), Tok.getLocation(), Toks, + Lexer::getSourceText( + {{Toks.begin()->getLocation(), Tok.getLocation()}, false}, + Actions.getASTContext().getSourceManager(), getLangOpts())); + BodyScope.Exit(); + + return Actions.ActOnFinishFunctionBody(Res, Body.get()); + } else if (CurParsedObjCImpl && !TemplateInfo.TemplateParams && + (Tok.is(tok::l_brace) || Tok.is(tok::kw_try) || + Tok.is(tok::colon)) && + Actions.CurContext->isTranslationUnit()) { ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); Scope *ParentScope = getCurScope()->getParent(); Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Jun 15 06:19:39 2016 @@ -2213,11 +2213,11 @@ Sema::ActOnIdExpression(Scope *S, CXXSco bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen); if (R.empty() && !ADL) { - if (SS.isEmpty() && getLangOpts().MSVCCompat) { - if (Expr *E = recoverFromMSUnqualifiedLookup(*this, Context, NameInfo, - TemplateKWLoc, TemplateArgs)) - return E; - } + // if (SS.isEmpty() && getLangOpts().MSVCCompat) { + // if (Expr *E = recoverFromMSUnqualifiedLookup(*this, Context, NameInfo, + // TemplateKWLoc, TemplateArgs)) + // return E; + // } // Don't diagnose an empty lookup for inline assembly. if (IsInlineAsmIdentifier) Modified: cfe/trunk/lib/Sema/SemaStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaStmt.cpp (original) +++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed Jun 15 06:19:39 2016 @@ -3978,3 +3978,30 @@ StmtResult Sema::ActOnCapturedRegionEnd( return Res; } + +StmtResult Sema::ActOnMSLateParsedCompoundStmt(SourceLocation LB, + SourceLocation RB, + ArrayRef<Token> Tokens, + StringRef Rep) { + if (CurContext->isDependentContext()) + return MSLateParsedCompoundStmt::Create(getASTContext(), LB, RB, Tokens, + Rep); + + QualType CXXThisTy = getCurrentThisType(); + assert(!CXXThisTy.isNull()); + auto *CXXThisRD = CXXThisTy->castAs<PointerType>() + ->getPointeeCXXRecordDecl() + ->getCanonicalDecl(); + DeclContext *DC = getFunctionLevelDeclContext(); + while (auto *PCXXRD = dyn_cast<CXXRecordDecl>(DC)) { + if (PCXXRD->getCanonicalDecl() == CXXThisRD) + break; + DC = DC->getParent(); + } + auto *MD = dyn_cast<CXXMethodDecl>(DC); + LateParsedTemplate LPT; + LPT.Toks.append(Tokens.begin(), Tokens.end()); + LPT.D = MD; + LateTemplateParser(OpaqueParser, LPT); + return MD->getBody(); +} Modified: cfe/trunk/lib/Sema/TreeTransform.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/lib/Sema/TreeTransform.h (original) +++ cfe/trunk/lib/Sema/TreeTransform.h Wed Jun 15 06:19:39 2016 @@ -1292,6 +1292,17 @@ public: Constraints, Clobbers, Exprs, EndLoc); } + /// Build a new compound statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildMSLateParsedCompoundStmt(SourceLocation LB, + SourceLocation RB, + ArrayRef<Token> Tokens, + StringRef Rep) { + return getSema().ActOnMSLateParsedCompoundStmt(LB, RB, Tokens, Rep); + } + /// \brief Build a new co_return statement. /// /// By default, performs semantic analysis to build the new statement. @@ -6606,6 +6617,16 @@ TreeTransform<Derived>::TransformMSAsmSt TransformedExprs, S->getEndLoc()); } +template <typename Derived> +StmtResult TreeTransform<Derived>::TransformMSLateParsedCompoundStmt( + MSLateParsedCompoundStmt *S) { + if (SemaRef.CurContext->isDependentContext()) + return S; + return getDerived().RebuildMSLateParsedCompoundStmt( + S->getLocStart(), S->getLocEnd(), S->tokens(), + S->getStringRepresentation()); +} + // C++ Coroutines TS template<typename Derived> Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Wed Jun 15 06:19:39 2016 @@ -382,6 +382,21 @@ void ASTStmtReader::VisitMSAsmStmt(MSAsm Constraints, Exprs, Clobbers); } +void ASTStmtReader::VisitMSLateParsedCompoundStmt(MSLateParsedCompoundStmt *S) { + VisitStmt(S); + SourceLocation LB = ReadSourceLocation(Record, Idx); + SourceLocation RB = ReadSourceLocation(Record, Idx); + std::string StringRep = ReadString(Record, Idx); + unsigned NumToks = Record[Idx++]; + + // Read the tokens. + SmallVector<Token, 16> Toks; + Toks.reserve(NumToks); + for (unsigned I = 0, E = NumToks; I != E; ++I) + Toks.push_back(ReadToken(Record, Idx)); + S->init(Reader.getContext(), LB, RB, Toks, StringRep); +} + void ASTStmtReader::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) { // FIXME: Implement coroutine serialization. llvm_unreachable("unimplemented"); @@ -2867,6 +2882,11 @@ Stmt *ASTReader::ReadStmtFromStream(Modu S = new (Context) MSAsmStmt(Empty); break; + case STMT_MS_LATE_PARSED_COMPOUND: + S = MSLateParsedCompoundStmt::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields]); + break; + case STMT_CAPTURED: S = CapturedStmt::CreateDeserialized(Context, Record[ASTStmtReader::NumStmtFields]); Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Wed Jun 15 06:19:39 2016 @@ -297,6 +297,18 @@ void ASTStmtWriter::VisitMSAsmStmt(MSAsm Code = serialization::STMT_MSASM; } +void ASTStmtWriter::VisitMSLateParsedCompoundStmt(MSLateParsedCompoundStmt *S) { + VisitStmt(S); + Record.push_back(S->tokens().size()); + Record.AddSourceLocation(S->getLocStart()); + Record.AddSourceLocation(S->getLocEnd()); + Record.AddString(S->getStringRepresentation()); + for (auto &Tok : S->tokens()) + Writer.AddToken(Tok, Record.getRecordData()); + + Code = serialization::STMT_MS_LATE_PARSED_COMPOUND; +} + void ASTStmtWriter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) { // FIXME: Implement coroutine serialization. llvm_unreachable("unimplemented"); Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed Jun 15 06:19:39 2016 @@ -808,6 +808,7 @@ void ExprEngine::Visit(const Stmt *S, Ex case Stmt::SwitchStmtClass: case Stmt::WhileStmtClass: case Expr::MSDependentExistsStmtClass: + case Expr::MSLateParsedCompoundStmtClass: case Stmt::CapturedStmtClass: case Stmt::OMPParallelDirectiveClass: case Stmt::OMPSimdDirectiveClass: Modified: cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp (original) +++ cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp Wed Jun 15 06:19:39 2016 @@ -556,6 +556,7 @@ struct Base { template <typename T> struct Template : T { void member() { f(); // expected-warning {{found via unqualified lookup into dependent bases}} + T::f(); } }; void test() { Modified: cfe/trunk/tools/libclang/CIndex.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CIndex.cpp (original) +++ cfe/trunk/tools/libclang/CIndex.cpp Wed Jun 15 06:19:39 2016 @@ -4632,6 +4632,8 @@ CXString clang_getCursorKindSpelling(enu return cxstring::createRef("GCCAsmStmt"); case CXCursor_MSAsmStmt: return cxstring::createRef("MSAsmStmt"); + case CXCursor_MSLateParsedCompoundStmt: + return cxstring::createRef("MSLateParsedCompoundStmt"); case CXCursor_ObjCAtTryStmt: return cxstring::createRef("ObjCAtTryStmt"); case CXCursor_ObjCAtCatchStmt: Modified: cfe/trunk/tools/libclang/CXCursor.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=272774&r1=272773&r2=272774&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CXCursor.cpp (original) +++ cfe/trunk/tools/libclang/CXCursor.cpp Wed Jun 15 06:19:39 2016 @@ -168,6 +168,10 @@ CXCursor cxcursor::MakeCXCursor(const St K = CXCursor_MSAsmStmt; break; + case Stmt::MSLateParsedCompoundStmtClass: + K = CXCursor_MSLateParsedCompoundStmt; + break; + case Stmt::ObjCAtTryStmtClass: K = CXCursor_ObjCAtTryStmt; break; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits