r272774 - [MSVC] Late parsing of in-class defined member functions in template

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 15 04:19:41 PDT 2016


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;




More information about the cfe-commits mailing list