diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -941,8 +941,8 @@ bool isActive; public: - explicit TentativeParsingAction(Parser& p) : P(p) { - PrevPreferredType = P.PreferredType; + explicit TentativeParsingAction(Parser &p) + : P(p), PrevPreferredType(P.PreferredType) { PrevTok = P.Tok; PrevTentativelyDeclaredIdentifierCount = P.TentativelyDeclaredIdentifiers.size(); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -286,14 +286,13 @@ } }; -/// Keeps track of expected type during expression parsing. The type is tied to -/// a particular token, all functions that update or consume the type take a -/// start location of the token they are looking at as a parameter. This allows -/// to avoid updating the type on hot paths in the parser. +/// Tracks expected type during expression parsing, for use in code completion. +/// The type is tied to a particular token, all functions that update or consume +/// the type take a start location of the token they are looking at as a +/// parameter. This avoids updating the type on hot paths in the parser. class PreferredTypeBuilder { public: - PreferredTypeBuilder() = default; - explicit PreferredTypeBuilder(QualType Type) : Type(Type) {} + PreferredTypeBuilder(bool Enabled) : Enabled(Enabled) {} void enterCondition(Sema &S, SourceLocation Tok); void enterReturn(Sema &S, SourceLocation Tok); @@ -320,7 +319,7 @@ void enterTypeCast(SourceLocation Tok, QualType CastType); QualType get(SourceLocation Tok) const { - if (Tok != ExpectedLoc) + if (!Enabled || Tok != ExpectedLoc) return QualType(); if (!Type.isNull()) return Type; @@ -330,6 +329,7 @@ } private: + bool Enabled; /// Start position of a token for which we store expected type. SourceLocation ExpectedLoc; /// Expected type for a token starting at ExpectedLoc. diff --git a/clang/lib/Parse/ParseInit.cpp b/clang/lib/Parse/ParseInit.cpp --- a/clang/lib/Parse/ParseInit.cpp +++ b/clang/lib/Parse/ParseInit.cpp @@ -160,9 +160,6 @@ /// \p CodeCompleteCB is called with Designation parsed so far. ExprResult Parser::ParseInitializerWithPotentialDesignator( DesignatorCompletionInfo DesignatorCompletion) { - if (!getPreprocessor().isCodeCompletionEnabled()) - DesignatorCompletion.PreferredBaseType = QualType(); // skip field lookup - // If this is the old-style GNU extension: // designation ::= identifier ':' // Handle it as a field designator. Otherwise, this must be the start of a diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -49,10 +49,10 @@ } Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) - : PP(pp), Actions(actions), Diags(PP.getDiagnostics()), - GreaterThanIsOperator(true), ColonIsSacred(false), - InMessageExpression(false), TemplateParameterDepth(0), - ParsingInObjCContainer(false) { + : PP(pp), PreferredType(pp.isCodeCompletionEnabled()), Actions(actions), + Diags(PP.getDiagnostics()), GreaterThanIsOperator(true), + ColonIsSacred(false), InMessageExpression(false), + TemplateParameterDepth(0), ParsingInObjCContainer(false) { SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies; Tok.startToken(); Tok.setKind(tok::eof); diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -381,6 +381,8 @@ } // namespace void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) { + if (!Enabled) + return; if (isa(S.CurContext)) { if (sema::BlockScopeInfo *BSI = S.getCurBlock()) { ComputeType = nullptr; @@ -399,6 +401,8 @@ } void PreferredTypeBuilder::enterVariableInit(SourceLocation Tok, Decl *D) { + if (!Enabled) + return; auto *VD = llvm::dyn_cast_or_null(D); ComputeType = nullptr; Type = VD ? VD->getType() : QualType(); @@ -410,6 +414,8 @@ void PreferredTypeBuilder::enterDesignatedInitializer(SourceLocation Tok, QualType BaseType, const Designation &D) { + if (!Enabled) + return; ComputeType = nullptr; Type = getDesignatedType(BaseType, D); ExpectedLoc = Tok; @@ -417,6 +423,8 @@ void PreferredTypeBuilder::enterFunctionArgument( SourceLocation Tok, llvm::function_ref ComputeType) { + if (!Enabled) + return; this->ComputeType = ComputeType; Type = QualType(); ExpectedLoc = Tok; @@ -424,6 +432,8 @@ void PreferredTypeBuilder::enterParenExpr(SourceLocation Tok, SourceLocation LParLoc) { + if (!Enabled) + return; // expected type for parenthesized expression does not change. if (ExpectedLoc == LParLoc) ExpectedLoc = Tok; @@ -541,6 +551,8 @@ void PreferredTypeBuilder::enterBinary(Sema &S, SourceLocation Tok, Expr *LHS, tok::TokenKind Op) { + if (!Enabled) + return; ComputeType = nullptr; Type = getPreferredTypeOfBinaryRHS(S, LHS, Op); ExpectedLoc = Tok; @@ -548,7 +560,7 @@ void PreferredTypeBuilder::enterMemAccess(Sema &S, SourceLocation Tok, Expr *Base) { - if (!Base) + if (!Enabled || !Base) return; // Do we have expected type for Base? if (ExpectedLoc != Base->getBeginLoc()) @@ -561,6 +573,8 @@ void PreferredTypeBuilder::enterUnary(Sema &S, SourceLocation Tok, tok::TokenKind OpKind, SourceLocation OpLoc) { + if (!Enabled) + return; ComputeType = nullptr; Type = getPreferredTypeOfUnaryArg(S, this->get(OpLoc), OpKind); ExpectedLoc = Tok; @@ -568,6 +582,8 @@ void PreferredTypeBuilder::enterSubscript(Sema &S, SourceLocation Tok, Expr *LHS) { + if (!Enabled) + return; ComputeType = nullptr; Type = S.getASTContext().IntTy; ExpectedLoc = Tok; @@ -575,12 +591,16 @@ void PreferredTypeBuilder::enterTypeCast(SourceLocation Tok, QualType CastType) { + if (!Enabled) + return; ComputeType = nullptr; Type = !CastType.isNull() ? CastType.getCanonicalType() : QualType(); ExpectedLoc = Tok; } void PreferredTypeBuilder::enterCondition(Sema &S, SourceLocation Tok) { + if (!Enabled) + return; ComputeType = nullptr; Type = S.getASTContext().BoolTy; ExpectedLoc = Tok;