diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Driver/ToolChains/Clang.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Lex/Lexer.cpp | 33 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCXXScopeSpec.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 6 |
7 files changed, 56 insertions, 0 deletions
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index b6887b87584..49708e7d724 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2306,6 +2306,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasFlag(options::OPT_fstrict_return, options::OPT_fno_strict_return, true)) CmdArgs.push_back("-fno-strict-return"); + if (Args.hasFlag(options::OPT_fallow_editor_placeholders, + options::OPT_fno_allow_editor_placeholders, false)) + CmdArgs.push_back("-fallow-editor-placeholders"); if (Args.hasFlag(options::OPT_fstrict_vtable_pointers, options::OPT_fno_strict_vtable_pointers, false)) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 05db4577ab9..0e0eb40eb33 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2322,6 +2322,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Args.getAllArgValues(OPT_fxray_always_instrument); Opts.XRayNeverInstrumentFiles = Args.getAllArgValues(OPT_fxray_never_instrument); + + // -fallow-editor-placeholders + Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders); } static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index dc911ef91b6..003c9b5eed1 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -2716,6 +2716,37 @@ bool Lexer::HandleEndOfConflictMarker(const char *CurPtr) { return false; } +static const char *findPlaceholderEnd(const char *CurPtr, + const char *BufferEnd) { + if (CurPtr == BufferEnd) + return nullptr; + BufferEnd -= 1; // Scan until the second last character. + for (; CurPtr != BufferEnd; ++CurPtr) { + if (CurPtr[0] == '#' && CurPtr[1] == '>') + return CurPtr + 2; + } + return nullptr; +} + +bool Lexer::lexEditorPlaceholder(Token &Result, const char *CurPtr) { + assert(CurPtr[-1] == '<' && CurPtr[0] == '#' && "Not a placeholder!"); + if (!PP || LexingRawMode) + return false; + const char *End = findPlaceholderEnd(CurPtr + 1, BufferEnd); + if (!End) + return false; + const char *Start = CurPtr - 1; + if (!LangOpts.AllowEditorPlaceholders) + Diag(Start, diag::err_placeholder_in_source); + Result.startToken(); + FormTokenWithChars(Result, End, tok::raw_identifier); + Result.setRawIdentifierData(Start); + PP->LookUpIdentifierInfo(Result); + Result.setFlag(Token::IsEditorPlaceholder); + BufferPtr = End; + return true; +} + bool Lexer::isCodeCompletionPoint(const char *CurPtr) const { if (PP && PP->isCodeCompletionEnabled()) { SourceLocation Loc = FileLoc.getLocWithOffset(CurPtr-BufferStart); @@ -3473,6 +3504,8 @@ LexNextToken: } else if (LangOpts.Digraphs && Char == '%') { // '<%' -> '{' CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); Kind = tok::l_brace; + } else if (Char == '#' && lexEditorPlaceholder(Result, CurPtr)) { + return true; } else { Kind = tok::less; } diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 265c12d7d5e..edbfc636bc4 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -851,6 +851,10 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, default: dont_know: + if (Tok.isEditorPlaceholder()) { + ConsumeToken(); + return nullptr; + } // We can't tell whether this is a function-definition or declaration yet. return ParseDeclarationOrFunctionDefinition(attrs, DS); } @@ -1679,6 +1683,8 @@ bool Parser::TryAnnotateTypeOrScopeToken() { return false; } } + if (Tok.isEditorPlaceholder()) + return true; Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename); return true; diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 57471de78d3..6da4d2a2619 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -480,6 +480,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, bool ErrorRecoveryLookup, bool *IsCorrectedToColon, bool OnlyNamespace) { + if (IdInfo.Identifier->isEditorPlaceholder()) + return true; LookupResult Found(*this, IdInfo.Identifier, IdInfo.IdentifierLoc, OnlyNamespace ? LookupNamespaceName : LookupNestedNameSpecifierName); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 075e87b75cd..f3ffcf5d696 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -628,6 +628,9 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, CXXScopeSpec *SS, ParsedType &SuggestedType, bool AllowClassTemplates) { + // Don't report typename errors for editor placeholders. + if (II->isEditorPlaceholder()) + return; // We don't have anything to suggest (yet). SuggestedType = nullptr; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index bb174521c72..5a56f709377 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2129,6 +2129,12 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, IdentifierInfo *II = Name.getAsIdentifierInfo(); SourceLocation NameLoc = NameInfo.getLoc(); + if (II && II->isEditorPlaceholder()) { + // FIXME: When typed placeholders are supported we can create a typed + // placeholder expression node. + return ExprError(); + } + // C++ [temp.dep.expr]p3: // An id-expression is type-dependent if it contains: // -- an identifier that was declared with a dependent type, |