[PATCH] D39279: Stringizing raw string literals containing newline
twoh created this revision. This patch implements 4.3 of http://open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4220.pdf. If a raw string contains a newline character, replace each newline character with the \n escape code. Without this patch, included test case (macro_raw_string.cpp) results compilation failure. https://reviews.llvm.org/D39279 Files: lib/Lex/Lexer.cpp test/Preprocessor/macro_raw_string.cpp unittests/Lex/LexerTest.cpp Index: unittests/Lex/LexerTest.cpp === --- unittests/Lex/LexerTest.cpp +++ unittests/Lex/LexerTest.cpp @@ -37,7 +37,7 @@ DiagID(new DiagnosticIDs()), Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), - TargetOpts(new TargetOptions) + TargetOpts(new TargetOptions) { TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); @@ -478,4 +478,18 @@ EXPECT_TRUE(LexedTokens.empty()); } +TEST_F(LexerTest, StringizingRasString) { + std::string String1 = R"(foo +{"bar":[]} +baz)"; + SmallString<128> String2; + String2 += String1.c_str(); + + String1 = Lexer::Stringify(StringRef(String1)); + Lexer::Stringify(String2); + + EXPECT_EQ(String1, R"(foo\n{\"bar\":[]}\nbaz)"); + EXPECT_EQ(String2, R"(foo\n{\"bar\":[]}\nbaz)"); +} + } // anonymous namespace Index: test/Preprocessor/macro_raw_string.cpp === --- /dev/null +++ test/Preprocessor/macro_raw_string.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -E -std=c++11 %s -o %t +// RUN: %clang_cc1 %t + +#define FOO(str) foo(#str) + +extern void foo(const char *str); + +void bar() { + FOO(R"(foo +bar)"); +} Index: lib/Lex/Lexer.cpp === --- lib/Lex/Lexer.cpp +++ lib/Lex/Lexer.cpp @@ -210,27 +210,46 @@ } /// Stringify - Convert the specified string into a C string, with surrounding -/// ""'s, and with escaped \ and " characters. +/// ""'s, and with escaped \ and " characters. The function replaces each +/// newline character with the "\n" escape code as well. std::string Lexer::Stringify(StringRef Str, bool Charify) { std::string Result = Str; char Quote = Charify ? '\'' : '"'; - for (unsigned i = 0, e = Result.size(); i != e; ++i) { + for (unsigned i = 0, e = Result.size(); i < e; ++i) { if (Result[i] == '\\' || Result[i] == Quote) { Result.insert(Result.begin()+i, '\\'); ++i; ++e; } +else if (auto Size = getEscapedNewLineSize(Result.substr(i).data())) { + Result.erase(Result.begin()+i, Result.begin()+i+Size); + Result.insert(Result.begin()+i, '\\'); + Result.insert(Result.begin()+i+1, 'n'); + i+=2; e+=(2-Size); +} } return Result; } /// Stringify - Convert the specified string into a C string by escaping '\' -/// and " characters. This does not add surrounding ""'s to the string. +/// and " characters. The function replaces each newline character with the +/// "\n" escape code as well. This does not add surrounding ""'s to the string. void Lexer::Stringify(SmallVectorImpl &Str) { - for (unsigned i = 0, e = Str.size(); i != e; ++i) { + for (unsigned i = 0, e = Str.size(); i < e; ++i) { if (Str[i] == '\\' || Str[i] == '"') { Str.insert(Str.begin()+i, '\\'); ++i; ++e; } +else if (Str[i] == '\n' || Str[i] == '\r') { + unsigned Size = 1; + if ((i < e-1) && (Str[i+1] == '\n' || Str[i+1] == '\r') && + Str[i] != Str[i+1]) +Size += 1; + + Str.erase(Str.begin()+i, Str.begin()+i+Size); + Str.insert(Str.begin()+i, '\\'); + Str.insert(Str.begin()+i+1, 'n'); + i+=2; e+=(2-Size); +} } } @@ -367,7 +386,7 @@ /// to point to a constant buffer with the data already in it (avoiding a /// copy). The caller is not allowed to modify the returned buffer pointer /// if an internal buffer is returned. -unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, +unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, const LangOptions &LangOpts, bool *Invalid) { assert((int)Tok.getLength() >= 0 && "Token character range is bogus!"); @@ -592,17 +611,17 @@ if (TheTok.getKind() == tok::eof) { break; } - + // If we haven't hit the end of the preprocessor directive, skip this // token. if (!TheTok.isAtStartOfLine()) continue; - + // We've passed the end of the preprocessor directive, and will look // at this token again below. InPreprocessorDirective = false; } - + // Keep track of the # of lines in the preamble. if (TheTok.isAtStartOfLine()) { unsigned TokOffset = TheTok.getLocation().getRawEncoding() - StartOffset; @
[PATCH] D39279: Stringizing raw string literals containing newline
twoh updated this revision to Diff 120195. twoh added a comment. clang-format https://reviews.llvm.org/D39279 Files: lib/Lex/Lexer.cpp test/Preprocessor/macro_raw_string.cpp unittests/Lex/LexerTest.cpp Index: unittests/Lex/LexerTest.cpp === --- unittests/Lex/LexerTest.cpp +++ unittests/Lex/LexerTest.cpp @@ -37,7 +37,7 @@ DiagID(new DiagnosticIDs()), Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), - TargetOpts(new TargetOptions) + TargetOpts(new TargetOptions) { TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); @@ -478,4 +478,18 @@ EXPECT_TRUE(LexedTokens.empty()); } +TEST_F(LexerTest, StringizingRasString) { + std::string String1 = R"(foo +{"bar":[]} +baz)"; + SmallString<128> String2; + String2 += String1.c_str(); + + String1 = Lexer::Stringify(StringRef(String1)); + Lexer::Stringify(String2); + + EXPECT_EQ(String1, R"(foo\n{\"bar\":[]}\nbaz)"); + EXPECT_EQ(String2, R"(foo\n{\"bar\":[]}\nbaz)"); +} + } // anonymous namespace Index: test/Preprocessor/macro_raw_string.cpp === --- /dev/null +++ test/Preprocessor/macro_raw_string.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -E -std=c++11 %s -o %t +// RUN: %clang_cc1 %t + +#define FOO(str) foo(#str) + +extern void foo(const char *str); + +void bar() { + FOO(R"(foo +bar)"); +} Index: lib/Lex/Lexer.cpp === --- lib/Lex/Lexer.cpp +++ lib/Lex/Lexer.cpp @@ -210,26 +210,47 @@ } /// Stringify - Convert the specified string into a C string, with surrounding -/// ""'s, and with escaped \ and " characters. +/// ""'s, and with escaped \ and " characters. The function replaces each +/// newline character with the "\n" escape code as well. std::string Lexer::Stringify(StringRef Str, bool Charify) { std::string Result = Str; char Quote = Charify ? '\'' : '"'; - for (unsigned i = 0, e = Result.size(); i != e; ++i) { + for (unsigned i = 0, e = Result.size(); i < e; ++i) { if (Result[i] == '\\' || Result[i] == Quote) { - Result.insert(Result.begin()+i, '\\'); - ++i; ++e; + Result.insert(Result.begin() + i, '\\'); + ++i; + ++e; +} else if (auto Size = getEscapedNewLineSize(Result.substr(i).data())) { + Result.erase(Result.begin() + i, Result.begin() + i + Size); + Result.insert(Result.begin() + i, '\\'); + Result.insert(Result.begin() + i + 1, 'n'); + i += 2; + e += (2 - Size); } } return Result; } /// Stringify - Convert the specified string into a C string by escaping '\' -/// and " characters. This does not add surrounding ""'s to the string. +/// and " characters. The function replaces each newline character with the +/// "\n" escape code as well. This does not add surrounding ""'s to the string. void Lexer::Stringify(SmallVectorImpl &Str) { - for (unsigned i = 0, e = Str.size(); i != e; ++i) { + for (unsigned i = 0, e = Str.size(); i < e; ++i) { if (Str[i] == '\\' || Str[i] == '"') { - Str.insert(Str.begin()+i, '\\'); - ++i; ++e; + Str.insert(Str.begin() + i, '\\'); + ++i; + ++e; +} else if (Str[i] == '\n' || Str[i] == '\r') { + unsigned Size = 1; + if ((i < e - 1) && (Str[i + 1] == '\n' || Str[i + 1] == '\r') && + Str[i] != Str[i + 1]) +Size += 1; + + Str.erase(Str.begin() + i, Str.begin() + i + Size); + Str.insert(Str.begin() + i, '\\'); + Str.insert(Str.begin() + i + 1, 'n'); + i += 2; + e += (2 - Size); } } } @@ -367,7 +388,7 @@ /// to point to a constant buffer with the data already in it (avoiding a /// copy). The caller is not allowed to modify the returned buffer pointer /// if an internal buffer is returned. -unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, +unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, const LangOptions &LangOpts, bool *Invalid) { assert((int)Tok.getLength() >= 0 && "Token character range is bogus!"); @@ -592,17 +613,17 @@ if (TheTok.getKind() == tok::eof) { break; } - + // If we haven't hit the end of the preprocessor directive, skip this // token. if (!TheTok.isAtStartOfLine()) continue; - + // We've passed the end of the preprocessor directive, and will look // at this token again below. InPreprocessorDirective = false; } - + // Keep track of the # of lines in the preamble. if (TheTok.isAtStartOfLine()) { unsigned TokOffset = TheTok.getLocation().getRawEncoding() - StartOffset; @@ -619,13 +640,13 @@ ActiveCommentLoc = TheTok
[PATCH] D37310: [Atomic] Merge alignment information from Decl and from Type when emit atomic expression.
twoh added a comment. Herald added subscribers: llvm-commits, jfb. Hello, I observed a case where atomic builtin generates libcall when the corresponding sync builtin generates an atomic instruction (https://bugs.llvm.org/show_bug.cgi?id=38846). It seems that the alignment checking for __atomic builtins (line 759 of this patch) results the difference, and wonder if the check is actually necessary. Could anyone please shed some light on understanding this? Thanks! Repository: rL LLVM https://reviews.llvm.org/D37310 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38061: Set AnonymousTagLocations false for ASTContext if column info is expected not to be used
twoh updated this revision to Diff 164564. twoh edited the summary of this revision. twoh added a comment. Herald added a subscriber: cfe-commits. Addressing comments from @echristo. Reverted option name change, and added a test case. Sorry I haven't work on this code for a while so it took time to invent a test case. Repository: rC Clang https://reviews.llvm.org/D38061 Files: lib/AST/Expr.cpp lib/CodeGen/CGDebugInfo.cpp lib/Frontend/CompilerInstance.cpp test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp test/CodeGenCXX/debug-info-anonymous.cpp test/Sema/assign.c test/Sema/enum.c test/Sema/switch.c test/SemaCXX/condition.cpp test/SemaCXX/enum.cpp test/SemaCXX/lambda-expressions.cpp test/SemaCXX/pass-object-size.cpp test/SemaCXX/warn-sign-conversion.cpp Index: test/SemaCXX/warn-sign-conversion.cpp === --- test/SemaCXX/warn-sign-conversion.cpp +++ test/SemaCXX/warn-sign-conversion.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -verify -fsyntax-only -Wsign-conversion %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -dwarf-column-info -verify -fsyntax-only -Wsign-conversion %s // NOTE: When a 'enumeral mismatch' warning is implemented then expect several // of the following cases to be impacted. Index: test/SemaCXX/pass-object-size.cpp === --- test/SemaCXX/pass-object-size.cpp +++ test/SemaCXX/pass-object-size.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +// RUN: %clang_cc1 -dwarf-column-info -fsyntax-only -verify %s -std=c++11 namespace simple { int Foo(void *const p __attribute__((pass_object_size(0; Index: test/SemaCXX/lambda-expressions.cpp === --- test/SemaCXX/lambda-expressions.cpp +++ test/SemaCXX/lambda-expressions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify -fblocks %s +// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -dwarf-column-info -fsyntax-only -verify -fblocks %s namespace std { class type_info; }; Index: test/SemaCXX/enum.cpp === --- test/SemaCXX/enum.cpp +++ test/SemaCXX/enum.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++98 -verify -triple x86_64-apple-darwin %s -// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++11 -verify -triple x86_64-apple-darwin %s +// RUN: %clang_cc1 -dwarf-column-info -fsyntax-only -pedantic -std=c++98 -verify -triple x86_64-apple-darwin %s +// RUN: %clang_cc1 -dwarf-column-info -fsyntax-only -pedantic -std=c++11 -verify -triple x86_64-apple-darwin %s enum E { // expected-note{{previous definition is here}} Val1, Val2 Index: test/SemaCXX/condition.cpp === --- test/SemaCXX/condition.cpp +++ test/SemaCXX/condition.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -dwarf-column-info -fsyntax-only -verify -std=c++11 %s void test() { int x; Index: test/Sema/switch.c === --- test/Sema/switch.c +++ test/Sema/switch.c @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wswitch-enum -Wcovered-switch-default -triple x86_64-linux-gnu %s -void f (int z) { - while (z) { +// RUN: %clang_cc1 -dwarf-column-info -fsyntax-only -verify -Wswitch-enum -Wcovered-switch-default -triple x86_64-linux-gnu %s +void f (int z) { + while (z) { default: z--;// expected-error {{statement not in switch}} - } + } } void foo(int X) { @@ -22,7 +22,7 @@ } } -void test3(void) { +void test3(void) { // empty switch; switch (0); // expected-warning {{no case matching constant switch condition '0'}} \ // expected-warning {{switch statement has empty body}} \ @@ -45,33 +45,33 @@ case 0 ... g(): // expected-error {{expression is not an integer constant expression}} break; } - + switch (cond) { case 0 && g() ... 1 || g(): break; } - + switch (cond) { case g() // expected-error {{expression is not an integer constant expression}} && 0: break; } - + switch (cond) { case 0 ... g() // expected-error {{expression is not an integer constant expression}} || 1: break; } } -void test5(int z) { +void test5(int z) { switch(z) { default: // expected-note {{previous case defined here}} default: // expected-error {{multiple default labels in one switch}} break; } -} +} void test6() { char ch = 'a'; @@ -187,7 +187,7 @@ case 0 ... //expected-warning{{case value not in enumerated type 'enum (anonymous enum}} 1: //expected-warning{{case value not in enumerated type 'enum (anonymous enum}} case 2 ... 4: -case 5
[PATCH] D34796: upporting -f(no)-reorder-functions flag, clang side change
twoh updated this revision to Diff 170148. twoh added a comment. Herald added a subscriber: jfb. Rebase. Sorry I somehow missed the recent comments. I addresses @davidxl's comment on documentation. Thanks! Repository: rC Clang https://reviews.llvm.org/D34796 Files: docs/ClangCommandLineReference.rst include/clang/Driver/Options.td include/clang/Frontend/CodeGenOptions.def lib/CodeGen/BackendUtil.cpp lib/Driver/ToolChains/Clang.cpp lib/Frontend/CompilerInvocation.cpp test/CodeGen/Inputs/freorder-functions.prof test/CodeGen/freorder-functions.c test/Driver/function-sections.c Index: test/Driver/function-sections.c === --- test/Driver/function-sections.c +++ test/Driver/function-sections.c @@ -6,6 +6,8 @@ // CHECK-NODS-NOT: -fdata-sections // CHECK-US-NOT: -fno-unique-section-names // CHECK-NOUS: -fno-unique-section-names +// CHECK-RF-NOT: -fno-reorder-functions +// CHECK-NORF: -fno-reorder-functions // RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ // RUN: -target i386-unknown-linux \ @@ -72,3 +74,13 @@ // RUN: -target i386-unknown-linux \ // RUN: -fno-unique-section-names \ // RUN: | FileCheck --check-prefix=CHECK-NOUS %s + +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1\ +// RUN: -target i386-unknown-linux \ +// RUN: -freorder-functions \ +// RUN: | FileCheck --check-prefix=CHECK-RF %s + +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1\ +// RUN: -target i386-unknown-linux \ +// RUN: -fno-reorder-functions \ +// RUN: | FileCheck --check-prefix=CHECK-NORF %s Index: test/CodeGen/freorder-functions.c === --- /dev/null +++ test/CodeGen/freorder-functions.c @@ -0,0 +1,22 @@ +// REQUIRES: x86-registered-target + +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -o - < %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -fno-reorder-functions -o - < %s | FileCheck --check-prefix=CHECK-NOPREFIX %s + +// opt tool option precedes driver option. +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -fno-reorder-functions -mllvm -profile-guided-section-prefix=true -o - < %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -freorder-functions -mllvm -profile-guided-section-prefix=false -o - < %s | FileCheck --check-prefix=CHECK-NOPREFIX %s + +void hot_func() { + return; +} + +void cold_func() { + hot_func(); + return; +} + +// CHECK: .section .text.hot.hot_func,"ax",@progbits +// CHECK: .section .text.unlikely.cold_func,"ax",@progbits +// CHECK-NOPREFIX: .section .text.hot_func,"ax",@progbits +// CHECK-NOPREFIX: .section .text.cold_func,"ax",@progbits Index: test/CodeGen/Inputs/freorder-functions.prof === --- /dev/null +++ test/CodeGen/Inputs/freorder-functions.prof @@ -0,0 +1,5 @@ +hot_func:1000:0 + 1: 0 +cold_func:0:0 + 1: 1 + 2: 1 Index: lib/Frontend/CompilerInvocation.cpp === --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -756,6 +756,8 @@ Args.hasFlag(OPT_fstack_size_section, OPT_fno_stack_size_section, false); Opts.UniqueSectionNames = Args.hasFlag(OPT_funique_section_names, OPT_fno_unique_section_names, true); + Opts.ReorderFunctions = + Args.hasFlag(OPT_freorder_functions, OPT_fno_reorder_functions, true); Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions); Index: lib/Driver/ToolChains/Clang.cpp === --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -3891,6 +3891,10 @@ options::OPT_fno_unique_section_names, true)) CmdArgs.push_back("-fno-unique-section-names"); + if (!Args.hasFlag(options::OPT_freorder_functions, +options::OPT_fno_reorder_functions, true)) +CmdArgs.push_back("-fno-reorder-functions"); + if (auto *A = Args.getLastArg( options::OPT_finstrument_functions, options::OPT_finstrument_functions_after_inlining, @@ -3929,6 +3933,83 @@ Args.AddLastArg(CmdArgs, options::OPT_working_directory); + bool ARCMTEnabled = false; + if (!Args.hasArg(options::OPT_fno_objc_arc, options::OPT_fobjc_arc)) { +if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check, + options::OPT_ccc_arcmt_modify, + options::OPT_ccc_arcmt_migrate)) { + ARCMTE
[PATCH] D34796: upporting -f(no)-reorder-functions flag, clang side change
twoh added a comment. @joerg Sorry but I'm not sure if I understand your question. This doesn't pretend to honor source code order, but makes linker to place "hot" functions under .text.hot section (There's no guarantee of ordering between functions inside .hot.text section) while "cold" functions under .text.unlikely section. This is purely for performance. Repository: rC Clang https://reviews.llvm.org/D34796 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D34796: upporting -f(no)-reorder-functions flag, clang side change
twoh updated this revision to Diff 170205. twoh added a comment. Remove conflict line. Repository: rC Clang https://reviews.llvm.org/D34796 Files: docs/ClangCommandLineReference.rst include/clang/Driver/Options.td include/clang/Frontend/CodeGenOptions.def lib/CodeGen/BackendUtil.cpp lib/Driver/ToolChains/Clang.cpp lib/Frontend/CompilerInvocation.cpp test/CodeGen/Inputs/freorder-functions.prof test/CodeGen/freorder-functions.c test/Driver/function-sections.c Index: test/Driver/function-sections.c === --- test/Driver/function-sections.c +++ test/Driver/function-sections.c @@ -6,6 +6,8 @@ // CHECK-NODS-NOT: -fdata-sections // CHECK-US-NOT: -fno-unique-section-names // CHECK-NOUS: -fno-unique-section-names +// CHECK-RF-NOT: -fno-reorder-functions +// CHECK-NORF: -fno-reorder-functions // RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ // RUN: -target i386-unknown-linux \ @@ -72,3 +74,13 @@ // RUN: -target i386-unknown-linux \ // RUN: -fno-unique-section-names \ // RUN: | FileCheck --check-prefix=CHECK-NOUS %s + +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1\ +// RUN: -target i386-unknown-linux \ +// RUN: -freorder-functions \ +// RUN: | FileCheck --check-prefix=CHECK-RF %s + +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1\ +// RUN: -target i386-unknown-linux \ +// RUN: -fno-reorder-functions \ +// RUN: | FileCheck --check-prefix=CHECK-NORF %s Index: test/CodeGen/freorder-functions.c === --- /dev/null +++ test/CodeGen/freorder-functions.c @@ -0,0 +1,22 @@ +// REQUIRES: x86-registered-target + +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -o - < %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -fno-reorder-functions -o - < %s | FileCheck --check-prefix=CHECK-NOPREFIX %s + +// opt tool option precedes driver option. +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -fno-reorder-functions -mllvm -profile-guided-section-prefix=true -o - < %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -freorder-functions -mllvm -profile-guided-section-prefix=false -o - < %s | FileCheck --check-prefix=CHECK-NOPREFIX %s + +void hot_func() { + return; +} + +void cold_func() { + hot_func(); + return; +} + +// CHECK: .section .text.hot.hot_func,"ax",@progbits +// CHECK: .section .text.unlikely.cold_func,"ax",@progbits +// CHECK-NOPREFIX: .section .text.hot_func,"ax",@progbits +// CHECK-NOPREFIX: .section .text.cold_func,"ax",@progbits Index: test/CodeGen/Inputs/freorder-functions.prof === --- /dev/null +++ test/CodeGen/Inputs/freorder-functions.prof @@ -0,0 +1,5 @@ +hot_func:1000:0 + 1: 0 +cold_func:0:0 + 1: 1 + 2: 1 Index: lib/Frontend/CompilerInvocation.cpp === --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -756,6 +756,8 @@ Args.hasFlag(OPT_fstack_size_section, OPT_fno_stack_size_section, false); Opts.UniqueSectionNames = Args.hasFlag(OPT_funique_section_names, OPT_fno_unique_section_names, true); + Opts.ReorderFunctions = + Args.hasFlag(OPT_freorder_functions, OPT_fno_reorder_functions, true); Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions); Index: lib/Driver/ToolChains/Clang.cpp === --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -3891,6 +3891,10 @@ options::OPT_fno_unique_section_names, true)) CmdArgs.push_back("-fno-unique-section-names"); + if (!Args.hasFlag(options::OPT_freorder_functions, +options::OPT_fno_reorder_functions, true)) +CmdArgs.push_back("-fno-reorder-functions"); + if (auto *A = Args.getLastArg( options::OPT_finstrument_functions, options::OPT_finstrument_functions_after_inlining, @@ -3929,6 +3933,82 @@ Args.AddLastArg(CmdArgs, options::OPT_working_directory); + bool ARCMTEnabled = false; + if (!Args.hasArg(options::OPT_fno_objc_arc, options::OPT_fobjc_arc)) { +if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check, + options::OPT_ccc_arcmt_modify, + options::OPT_ccc_arcmt_migrate)) { + ARCMTEnabled = true; + switch (A->getOption().getID()) { + default: +llvm_unreachable("missed a case"); +
[PATCH] D38061: Set AnonymousTagLocations false for ASTContext if column info is expected not to be used
twoh added a comment. @aprantl It is a debug info. If you compile test/CodeGenCXX/debug-info-anonymous.cpp file with `clang -g2 -emit-llvm -S `, you will find debug metadata something like `distinct !DISubprogram(name: "foo", linkageName: "_Z3fooIN1XUt_EEiT_" ...`, which will eventually be included in .debug_info section. Repository: rC Clang https://reviews.llvm.org/D38061 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38061: Set AnonymousTagLocations false for ASTContext if column info is expected not to be used
twoh added a comment. @dblaikie I see. The problem we're experiencing is that with Clang's naming scheme we end up having different function name between the original source and the preprocessed source (as macro expansion changes the column number). This doesn't work well for me if I want to use distcc on top of our caching system, as the caching scheme expects the output to be same as far as the original source has not been changed (regardless of it's compiled directly or first preprocessed then compiled), but the distcc preprocesses the source locally then sends it to the remote build machine (and we do not turn distcc on for all workflow). I wonder if you have any suggestion to resolve this issue? Thanks! Repository: rC Clang https://reviews.llvm.org/D38061 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38061: Set AnonymousTagLocations false for ASTContext if column info is expected not to be used
twoh added a comment. @rsmith @dblaikie Thank you for the comments! It seems that this is not the appropriate way to handle the issue. I'll find different way to resolve the problem. Repository: rC Clang https://reviews.llvm.org/D38061 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D53860: [SemaCXX] Don't check base's dtor is accessible
twoh added a comment. I think the context is Derived here. My understanding of http://wg21.link/p0968r0#2227 (in this patch's context) is that when Derived is aggregate initialized, the destructor for each element of Base is potentially invoked as well. For me it seems that the bug is checking destructor accessibility of Base itself, not fields of Base. I think the right fix for 1956-1960 is if (!VerifyOnly) { auto *BaseRD = Base.getType()->getAs()->getDecl(); for (FieldDecl *FD : BaseRD->fields()) { QualType ET = SemaRef.Context.getBaseElementType(FD->getType()); if (hasAccessibleDestructor(ET, InitLoc, SemaRef)) { hadError = true; return; } } } Repository: rC Clang https://reviews.llvm.org/D53860 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D53860: [SemaCXX] Don't check base's dtor is accessible
twoh added a comment. @rsmith I see. Thank you for the clarification! Repository: rC Clang https://reviews.llvm.org/D53860 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38061: Set AnonymousTagLocations false for ASTContext if column info is expected not to be used
twoh added a subscriber: wenlei. twoh added a comment. Herald added a subscriber: dexonsmith. Herald added a project: clang. Hello @rsmith, @wenlei and I took another look at this, and we couldn't find any use of `AnonymousTagLocations` outside of debug info. If that's actually the case, wouldn't it make sense to have `DebugColumnInfo` to control the field even if `AnonymousTagLocations` the part of generic printing policy? Repository: rC Clang CHANGES SINCE LAST ACTION https://reviews.llvm.org/D38061/new/ https://reviews.llvm.org/D38061 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38061: Set AnonymousTagLocations false for ASTContext if column info is expected not to be used
twoh added a comment. Friendly ping for comments. Thanks! Repository: rC Clang CHANGES SINCE LAST ACTION https://reviews.llvm.org/D38061/new/ https://reviews.llvm.org/D38061 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38061: Set AnonymousTagLocations false for ASTContext if column info is expected not to be used
twoh added a comment. ping! Repository: rC Clang https://reviews.llvm.org/D38061 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D65975: [NewPM][PassInstrumentation] IR printing support from clang driver
twoh created this revision. twoh added reviewers: fedor.sergeev, philip.pfaffe. Herald added a project: clang. Herald added a subscriber: cfe-commits. https://reviews.llvm.org/D50923 enabled the IR printing support for the new pass manager, but only for the case when `opt` tool is used as a driver. This patch is to enable the IR printing when `clang` is used as a driver. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D65975 Files: clang/lib/CodeGen/BackendUtil.cpp clang/test/Misc/printer.c Index: clang/test/Misc/printer.c === --- /dev/null +++ clang/test/Misc/printer.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -emit-llvm -O2 -fexperimental-new-pass-manager -mllvm -print-before-all %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-BEFORE +// RUN: %clang_cc1 -emit-llvm -O2 -fexperimental-new-pass-manager -mllvm -print-after-all %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-AFTER +// CHECK-BEFORE: *** IR Dump Before ForceFunctionAttrsPass *** +// CHECK-AFTER: *** IR Dump After ForceFunctionAttrsPass *** +void foo() {} Index: clang/lib/CodeGen/BackendUtil.cpp === --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -37,6 +37,7 @@ #include "llvm/MC/SubtargetFeature.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/PassPlugin.h" +#include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Support/BuryPointer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" @@ -1063,7 +1064,10 @@ PTO.LoopVectorization = CodeGenOpts.VectorizeLoop; PTO.SLPVectorization = CodeGenOpts.VectorizeSLP; - PassBuilder PB(TM.get(), PTO, PGOOpt); + PassInstrumentationCallbacks PIC; + StandardInstrumentations SI; + SI.registerCallbacks(PIC); + PassBuilder PB(TM.get(), PTO, PGOOpt, &PIC); // Attempt to load pass plugins and register their callbacks with PB. for (auto &PluginFN : CodeGenOpts.PassPlugins) { Index: clang/test/Misc/printer.c === --- /dev/null +++ clang/test/Misc/printer.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -emit-llvm -O2 -fexperimental-new-pass-manager -mllvm -print-before-all %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-BEFORE +// RUN: %clang_cc1 -emit-llvm -O2 -fexperimental-new-pass-manager -mllvm -print-after-all %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-AFTER +// CHECK-BEFORE: *** IR Dump Before ForceFunctionAttrsPass *** +// CHECK-AFTER: *** IR Dump After ForceFunctionAttrsPass *** +void foo() {} Index: clang/lib/CodeGen/BackendUtil.cpp === --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -37,6 +37,7 @@ #include "llvm/MC/SubtargetFeature.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/PassPlugin.h" +#include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Support/BuryPointer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" @@ -1063,7 +1064,10 @@ PTO.LoopVectorization = CodeGenOpts.VectorizeLoop; PTO.SLPVectorization = CodeGenOpts.VectorizeSLP; - PassBuilder PB(TM.get(), PTO, PGOOpt); + PassInstrumentationCallbacks PIC; + StandardInstrumentations SI; + SI.registerCallbacks(PIC); + PassBuilder PB(TM.get(), PTO, PGOOpt, &PIC); // Attempt to load pass plugins and register their callbacks with PB. for (auto &PluginFN : CodeGenOpts.PassPlugins) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D65975: [NewPM][PassInstrumentation] IR printing support from clang driver
twoh added a comment. @fedor.sergeev @yamauchi I saw your discussions over llvm-dev mailing list regarding IR printing with the new pass manager, and though this might be the reason why IR printing is not supported under new PM with clang. I would appreciate if you can take a look. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D65975/new/ https://reviews.llvm.org/D65975 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D65975: [NewPM][PassInstrumentation] IR printing support from clang driver
twoh updated this revision to Diff 214855. twoh added a comment. Avoid -O2 from the test. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D65975/new/ https://reviews.llvm.org/D65975 Files: clang/lib/CodeGen/BackendUtil.cpp clang/test/Misc/printer.c Index: clang/test/Misc/printer.c === --- /dev/null +++ clang/test/Misc/printer.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -emit-llvm -fexperimental-new-pass-manager -mllvm -print-before-all %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-BEFORE +// RUN: %clang_cc1 -emit-llvm -fexperimental-new-pass-manager -mllvm -print-after-all %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-AFTER +// CHECK-BEFORE: *** IR Dump Before AlwaysInlinerPass *** +// CHECK-AFTER: *** IR Dump After AlwaysInlinerPass *** +void foo() {} Index: clang/lib/CodeGen/BackendUtil.cpp === --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -37,6 +37,7 @@ #include "llvm/MC/SubtargetFeature.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/PassPlugin.h" +#include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Support/BuryPointer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" @@ -1063,7 +1064,10 @@ PTO.LoopVectorization = CodeGenOpts.VectorizeLoop; PTO.SLPVectorization = CodeGenOpts.VectorizeSLP; - PassBuilder PB(TM.get(), PTO, PGOOpt); + PassInstrumentationCallbacks PIC; + StandardInstrumentations SI; + SI.registerCallbacks(PIC); + PassBuilder PB(TM.get(), PTO, PGOOpt, &PIC); // Attempt to load pass plugins and register their callbacks with PB. for (auto &PluginFN : CodeGenOpts.PassPlugins) { Index: clang/test/Misc/printer.c === --- /dev/null +++ clang/test/Misc/printer.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -emit-llvm -fexperimental-new-pass-manager -mllvm -print-before-all %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-BEFORE +// RUN: %clang_cc1 -emit-llvm -fexperimental-new-pass-manager -mllvm -print-after-all %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-AFTER +// CHECK-BEFORE: *** IR Dump Before AlwaysInlinerPass *** +// CHECK-AFTER: *** IR Dump After AlwaysInlinerPass *** +void foo() {} Index: clang/lib/CodeGen/BackendUtil.cpp === --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -37,6 +37,7 @@ #include "llvm/MC/SubtargetFeature.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/PassPlugin.h" +#include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Support/BuryPointer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" @@ -1063,7 +1064,10 @@ PTO.LoopVectorization = CodeGenOpts.VectorizeLoop; PTO.SLPVectorization = CodeGenOpts.VectorizeSLP; - PassBuilder PB(TM.get(), PTO, PGOOpt); + PassInstrumentationCallbacks PIC; + StandardInstrumentations SI; + SI.registerCallbacks(PIC); + PassBuilder PB(TM.get(), PTO, PGOOpt, &PIC); // Attempt to load pass plugins and register their callbacks with PB. for (auto &PluginFN : CodeGenOpts.PassPlugins) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D65975: [NewPM][PassInstrumentation] IR printing support from clang driver
twoh added a comment. @fedor.sergeev Sorry for the late reply. I missed your comment. I found that with the new pass manager module verifier is not scheduled by default, and AlwaysInlinerPass is the only one scheduled if I provide no -O option. I removed -O2 from the test command and replaced ForceFunctionAttrPass to AlwaysInlinerPass. Thanks! Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D65975/new/ https://reviews.llvm.org/D65975 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D65975: [NewPM][PassInstrumentation] IR printing support from clang driver
This revision was automatically updated to reflect the committed changes. Closed by commit rL368804: [NewPM][PassInstrumentation] IR printing support from clang driver (authored by twoh, committed by ). Herald added a project: LLVM. Changed prior to commit: https://reviews.llvm.org/D65975?vs=214855&id=215034#toc Repository: rL LLVM CHANGES SINCE LAST ACTION https://reviews.llvm.org/D65975/new/ https://reviews.llvm.org/D65975 Files: cfe/trunk/lib/CodeGen/BackendUtil.cpp cfe/trunk/test/Misc/printer.c Index: cfe/trunk/test/Misc/printer.c === --- cfe/trunk/test/Misc/printer.c +++ cfe/trunk/test/Misc/printer.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -emit-llvm -fexperimental-new-pass-manager -mllvm -print-before-all %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-BEFORE +// RUN: %clang_cc1 -emit-llvm -fexperimental-new-pass-manager -mllvm -print-after-all %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-AFTER +// CHECK-BEFORE: *** IR Dump Before AlwaysInlinerPass *** +// CHECK-AFTER: *** IR Dump After AlwaysInlinerPass *** +void foo() {} Index: cfe/trunk/lib/CodeGen/BackendUtil.cpp === --- cfe/trunk/lib/CodeGen/BackendUtil.cpp +++ cfe/trunk/lib/CodeGen/BackendUtil.cpp @@ -37,6 +37,7 @@ #include "llvm/MC/SubtargetFeature.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/PassPlugin.h" +#include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Support/BuryPointer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" @@ -1063,7 +1064,10 @@ PTO.LoopVectorization = CodeGenOpts.VectorizeLoop; PTO.SLPVectorization = CodeGenOpts.VectorizeSLP; - PassBuilder PB(TM.get(), PTO, PGOOpt); + PassInstrumentationCallbacks PIC; + StandardInstrumentations SI; + SI.registerCallbacks(PIC); + PassBuilder PB(TM.get(), PTO, PGOOpt, &PIC); // Attempt to load pass plugins and register their callbacks with PB. for (auto &PluginFN : CodeGenOpts.PassPlugins) { Index: cfe/trunk/test/Misc/printer.c === --- cfe/trunk/test/Misc/printer.c +++ cfe/trunk/test/Misc/printer.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -emit-llvm -fexperimental-new-pass-manager -mllvm -print-before-all %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-BEFORE +// RUN: %clang_cc1 -emit-llvm -fexperimental-new-pass-manager -mllvm -print-after-all %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-AFTER +// CHECK-BEFORE: *** IR Dump Before AlwaysInlinerPass *** +// CHECK-AFTER: *** IR Dump After AlwaysInlinerPass *** +void foo() {} Index: cfe/trunk/lib/CodeGen/BackendUtil.cpp === --- cfe/trunk/lib/CodeGen/BackendUtil.cpp +++ cfe/trunk/lib/CodeGen/BackendUtil.cpp @@ -37,6 +37,7 @@ #include "llvm/MC/SubtargetFeature.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/PassPlugin.h" +#include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Support/BuryPointer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" @@ -1063,7 +1064,10 @@ PTO.LoopVectorization = CodeGenOpts.VectorizeLoop; PTO.SLPVectorization = CodeGenOpts.VectorizeSLP; - PassBuilder PB(TM.get(), PTO, PGOOpt); + PassInstrumentationCallbacks PIC; + StandardInstrumentations SI; + SI.registerCallbacks(PIC); + PassBuilder PB(TM.get(), PTO, PGOOpt, &PIC); // Attempt to load pass plugins and register their callbacks with PB. for (auto &PluginFN : CodeGenOpts.PassPlugins) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D39279: Stringizing raw string literals containing newline
twoh updated this revision to Diff 124515. twoh added a comment. Thanks @jkorous-apple for your comments. I modified the type for the variables and replaced unnecessary inserts and erases with updates. https://reviews.llvm.org/D39279 Files: include/clang/Lex/Lexer.h lib/Lex/Lexer.cpp test/Preprocessor/macro_raw_string.cpp unittests/Lex/LexerTest.cpp Index: unittests/Lex/LexerTest.cpp === --- unittests/Lex/LexerTest.cpp +++ unittests/Lex/LexerTest.cpp @@ -37,7 +37,7 @@ DiagID(new DiagnosticIDs()), Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), - TargetOpts(new TargetOptions) + TargetOpts(new TargetOptions) { TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); @@ -478,4 +478,42 @@ EXPECT_TRUE(LexedTokens.empty()); } +TEST_F(LexerTest, StringizingRasString) { + // For "std::string Lexer::Stringify(StringRef Str, bool Charify)". + std::string String1 = R"(foo +{"bar":[]} +baz)"; + // For "void Lexer::Stringify(SmallVectorImpl &Str)". + SmallString<128> String2; + String2 += String1.c_str(); + + // Corner cases. + std::string String3 = R"(\ +\n +\\n +\\)"; + SmallString<128> String4; + String4 += String3.c_str(); + std::string String5 = R"(a\ + + +\\b)"; + SmallString<128> String6; + String6 += String5.c_str(); + + String1 = Lexer::Stringify(StringRef(String1)); + Lexer::Stringify(String2); + String3 = Lexer::Stringify(StringRef(String3)); + Lexer::Stringify(String4); + String5 = Lexer::Stringify(StringRef(String5)); + Lexer::Stringify(String6); + + EXPECT_EQ(String1, R"(foo\n{\"bar\":[]}\nbaz)"); + EXPECT_EQ(String2, R"(foo\n{\"bar\":[]}\nbaz)"); + EXPECT_EQ(String3, R"(\\\n\\n\nn\n)"); + EXPECT_EQ(String4, R"(\\\n\\n\nn\n)"); + EXPECT_EQ(String5, R"(a\\\n\n\nb)"); + EXPECT_EQ(String6, R"(a\\\n\n\nb)"); +} + } // anonymous namespace Index: test/Preprocessor/macro_raw_string.cpp === --- /dev/null +++ test/Preprocessor/macro_raw_string.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -E -std=c++11 %s -o %t +// RUN: %clang_cc1 %t + +#define FOO(str) foo(#str) + +extern void foo(const char *str); + +void bar() { + FOO(R"(foo +bar)"); +} Index: lib/Lex/Lexer.cpp === --- lib/Lex/Lexer.cpp +++ lib/Lex/Lexer.cpp @@ -209,29 +209,44 @@ return L; } -/// Stringify - Convert the specified string into a C string, with surrounding -/// ""'s, and with escaped \ and " characters. +/// StringifyImpl - Implementation of Stringify functions. Convert the +/// specified string into a C string by i) escaping '\' and " characters and +/// ii) replacing newline character(s) with "\n". +template +void StringifyImpl(T& Str, char Quote) { + typename T::size_type i = 0, e = Str.size(); + while (i < e) { +if (Str[i] == '\\' || Str[i] == Quote) { + Str.insert(Str.begin() + i, '\\'); + i += 2; + ++e; +} else if (Str[i] == '\n' || Str[i] == '\r') { + // Replace '\r\n' and '\n\r' to '\\' followed by 'n'. + if ((i < e - 1) && (Str[i + 1] == '\n' || Str[i + 1] == '\r') && + Str[i] != Str[i + 1]) { +Str[i] = '\\'; +Str[i+1] = 'n'; + } else { +// Replace '\n' and '\r' to '\\' followed by 'n'. +Str[i] = '\\'; +Str.insert(Str.begin() + i + 1, 'n'); +++e; + } + i += 2; +} else + ++i; + } +} + std::string Lexer::Stringify(StringRef Str, bool Charify) { std::string Result = Str; char Quote = Charify ? '\'' : '"'; - for (unsigned i = 0, e = Result.size(); i != e; ++i) { -if (Result[i] == '\\' || Result[i] == Quote) { - Result.insert(Result.begin()+i, '\\'); - ++i; ++e; -} - } + StringifyImpl(Result, Quote); return Result; } -/// Stringify - Convert the specified string into a C string by escaping '\' -/// and " characters. This does not add surrounding ""'s to the string. void Lexer::Stringify(SmallVectorImpl &Str) { - for (unsigned i = 0, e = Str.size(); i != e; ++i) { -if (Str[i] == '\\' || Str[i] == '"') { - Str.insert(Str.begin()+i, '\\'); - ++i; ++e; -} - } + StringifyImpl(Str, '"'); } //===--===// @@ -367,7 +382,7 @@ /// to point to a constant buffer with the data already in it (avoiding a /// copy). The caller is not allowed to modify the returned buffer pointer /// if an internal buffer is returned. -unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, +unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, con
[PATCH] D39279: Stringizing raw string literals containing newline
twoh added a comment. @jkorous-apple Thanks for the comments! Yeah, I was thinking of O(lenght_of_string) approach, but considering the complicatedness of the implementation (I guess the real implementation would be a bit more complex than your pseudo implementation to handle quote and '\n\r' '\r\n' cases) I decided to stay with O(length_of_string * number_of_endlines_in_string) but optimizing the number of move operations. @vsapsai @jkorous-apple, I wonder if you can actually approve the patch or suggest other reviewers? Thanks! https://reviews.llvm.org/D39279 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D39279: Stringizing raw string literals containing newline
twoh updated this revision to Diff 125368. twoh added a comment. Thanks @jkorous-apple for the comment. I think your suggestion is a more precise description for the implementation, and adjusted the comments accordingly. I intentionally didn't add the details to the comments for the header, as LLVM coding standard "Don’t duplicate the documentation comment in the header file and in the implementation file. ... implementation files can include additional comments (not necessarily in Doxygen markup) to explain implementation details as needed." I'd like to leave it as of now if you're not strongly against it. Thank you again! https://reviews.llvm.org/D39279 Files: include/clang/Lex/Lexer.h lib/Lex/Lexer.cpp test/Preprocessor/macro_raw_string.cpp unittests/Lex/LexerTest.cpp Index: unittests/Lex/LexerTest.cpp === --- unittests/Lex/LexerTest.cpp +++ unittests/Lex/LexerTest.cpp @@ -37,7 +37,7 @@ DiagID(new DiagnosticIDs()), Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), - TargetOpts(new TargetOptions) + TargetOpts(new TargetOptions) { TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); @@ -478,4 +478,42 @@ EXPECT_TRUE(LexedTokens.empty()); } +TEST_F(LexerTest, StringizingRasString) { + // For "std::string Lexer::Stringify(StringRef Str, bool Charify)". + std::string String1 = R"(foo +{"bar":[]} +baz)"; + // For "void Lexer::Stringify(SmallVectorImpl &Str)". + SmallString<128> String2; + String2 += String1.c_str(); + + // Corner cases. + std::string String3 = R"(\ +\n +\\n +\\)"; + SmallString<128> String4; + String4 += String3.c_str(); + std::string String5 = R"(a\ + + +\\b)"; + SmallString<128> String6; + String6 += String5.c_str(); + + String1 = Lexer::Stringify(StringRef(String1)); + Lexer::Stringify(String2); + String3 = Lexer::Stringify(StringRef(String3)); + Lexer::Stringify(String4); + String5 = Lexer::Stringify(StringRef(String5)); + Lexer::Stringify(String6); + + EXPECT_EQ(String1, R"(foo\n{\"bar\":[]}\nbaz)"); + EXPECT_EQ(String2, R"(foo\n{\"bar\":[]}\nbaz)"); + EXPECT_EQ(String3, R"(\\\n\\n\nn\n)"); + EXPECT_EQ(String4, R"(\\\n\\n\nn\n)"); + EXPECT_EQ(String5, R"(a\\\n\n\nb)"); + EXPECT_EQ(String6, R"(a\\\n\n\nb)"); +} + } // anonymous namespace Index: test/Preprocessor/macro_raw_string.cpp === --- /dev/null +++ test/Preprocessor/macro_raw_string.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -E -std=c++11 %s -o %t +// RUN: %clang_cc1 %t + +#define FOO(str) foo(#str) + +extern void foo(const char *str); + +void bar() { + FOO(R"(foo +bar)"); +} Index: lib/Lex/Lexer.cpp === --- lib/Lex/Lexer.cpp +++ lib/Lex/Lexer.cpp @@ -209,29 +209,44 @@ return L; } -/// Stringify - Convert the specified string into a C string, with surrounding -/// ""'s, and with escaped \ and " characters. +/// StringifyImpl - Implementation of Stringify functions. Convert the +/// specified string into a C string by i) escaping '\\' and " characters and +/// ii) replacing newline character(s) with "\\n". +template +void StringifyImpl(T& Str, char Quote) { + typename T::size_type i = 0, e = Str.size(); + while (i < e) { +if (Str[i] == '\\' || Str[i] == Quote) { + Str.insert(Str.begin() + i, '\\'); + i += 2; + ++e; +} else if (Str[i] == '\n' || Str[i] == '\r') { + // Replace '\r\n' and '\n\r' to '\\' followed by 'n'. + if ((i < e - 1) && (Str[i + 1] == '\n' || Str[i + 1] == '\r') && + Str[i] != Str[i + 1]) { +Str[i] = '\\'; +Str[i+1] = 'n'; + } else { +// Replace '\n' and '\r' to '\\' followed by 'n'. +Str[i] = '\\'; +Str.insert(Str.begin() + i + 1, 'n'); +++e; + } + i += 2; +} else + ++i; + } +} + std::string Lexer::Stringify(StringRef Str, bool Charify) { std::string Result = Str; char Quote = Charify ? '\'' : '"'; - for (unsigned i = 0, e = Result.size(); i != e; ++i) { -if (Result[i] == '\\' || Result[i] == Quote) { - Result.insert(Result.begin()+i, '\\'); - ++i; ++e; -} - } + StringifyImpl(Result, Quote); return Result; } -/// Stringify - Convert the specified string into a C string by escaping '\' -/// and " characters. This does not add surrounding ""'s to the string. void Lexer::Stringify(SmallVectorImpl &Str) { - for (unsigned i = 0, e = Str.size(); i != e; ++i) { -if (Str[i] == '\\' || Str[i] == '"') { - Str.insert(Str.begin()+i, '\\'); - ++i; ++e; -} - } + StringifyImpl(Str, '"'); } //===--===// @@ -367,7
[PATCH] D39279: Stringizing raw string literals containing newline
twoh updated this revision to Diff 125563. twoh added a comment. @jkorous-apple Got it. I agree that it would be better to move the comments to the header. Will land it soon. Thanks! https://reviews.llvm.org/D39279 Files: include/clang/Lex/Lexer.h lib/Lex/Lexer.cpp test/Preprocessor/macro_raw_string.cpp unittests/Lex/LexerTest.cpp Index: unittests/Lex/LexerTest.cpp === --- unittests/Lex/LexerTest.cpp +++ unittests/Lex/LexerTest.cpp @@ -37,7 +37,7 @@ DiagID(new DiagnosticIDs()), Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), - TargetOpts(new TargetOptions) + TargetOpts(new TargetOptions) { TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); @@ -478,4 +478,42 @@ EXPECT_TRUE(LexedTokens.empty()); } +TEST_F(LexerTest, StringizingRasString) { + // For "std::string Lexer::Stringify(StringRef Str, bool Charify)". + std::string String1 = R"(foo +{"bar":[]} +baz)"; + // For "void Lexer::Stringify(SmallVectorImpl &Str)". + SmallString<128> String2; + String2 += String1.c_str(); + + // Corner cases. + std::string String3 = R"(\ +\n +\\n +\\)"; + SmallString<128> String4; + String4 += String3.c_str(); + std::string String5 = R"(a\ + + +\\b)"; + SmallString<128> String6; + String6 += String5.c_str(); + + String1 = Lexer::Stringify(StringRef(String1)); + Lexer::Stringify(String2); + String3 = Lexer::Stringify(StringRef(String3)); + Lexer::Stringify(String4); + String5 = Lexer::Stringify(StringRef(String5)); + Lexer::Stringify(String6); + + EXPECT_EQ(String1, R"(foo\n{\"bar\":[]}\nbaz)"); + EXPECT_EQ(String2, R"(foo\n{\"bar\":[]}\nbaz)"); + EXPECT_EQ(String3, R"(\\\n\\n\nn\n)"); + EXPECT_EQ(String4, R"(\\\n\\n\nn\n)"); + EXPECT_EQ(String5, R"(a\\\n\n\nb)"); + EXPECT_EQ(String6, R"(a\\\n\n\nb)"); +} + } // anonymous namespace Index: test/Preprocessor/macro_raw_string.cpp === --- /dev/null +++ test/Preprocessor/macro_raw_string.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -E -std=c++11 %s -o %t +// RUN: %clang_cc1 %t + +#define FOO(str) foo(#str) + +extern void foo(const char *str); + +void bar() { + FOO(R"(foo +bar)"); +} Index: lib/Lex/Lexer.cpp === --- lib/Lex/Lexer.cpp +++ lib/Lex/Lexer.cpp @@ -209,29 +209,41 @@ return L; } -/// Stringify - Convert the specified string into a C string, with surrounding -/// ""'s, and with escaped \ and " characters. +template +void StringifyImpl(T& Str, char Quote) { + typename T::size_type i = 0, e = Str.size(); + while (i < e) { +if (Str[i] == '\\' || Str[i] == Quote) { + Str.insert(Str.begin() + i, '\\'); + i += 2; + ++e; +} else if (Str[i] == '\n' || Str[i] == '\r') { + // Replace '\r\n' and '\n\r' to '\\' followed by 'n'. + if ((i < e - 1) && (Str[i + 1] == '\n' || Str[i + 1] == '\r') && + Str[i] != Str[i + 1]) { +Str[i] = '\\'; +Str[i+1] = 'n'; + } else { +// Replace '\n' and '\r' to '\\' followed by 'n'. +Str[i] = '\\'; +Str.insert(Str.begin() + i + 1, 'n'); +++e; + } + i += 2; +} else + ++i; + } +} + std::string Lexer::Stringify(StringRef Str, bool Charify) { std::string Result = Str; char Quote = Charify ? '\'' : '"'; - for (unsigned i = 0, e = Result.size(); i != e; ++i) { -if (Result[i] == '\\' || Result[i] == Quote) { - Result.insert(Result.begin()+i, '\\'); - ++i; ++e; -} - } + StringifyImpl(Result, Quote); return Result; } -/// Stringify - Convert the specified string into a C string by escaping '\' -/// and " characters. This does not add surrounding ""'s to the string. void Lexer::Stringify(SmallVectorImpl &Str) { - for (unsigned i = 0, e = Str.size(); i != e; ++i) { -if (Str[i] == '\\' || Str[i] == '"') { - Str.insert(Str.begin()+i, '\\'); - ++i; ++e; -} - } + StringifyImpl(Str, '"'); } //===--===// @@ -367,7 +379,7 @@ /// to point to a constant buffer with the data already in it (avoiding a /// copy). The caller is not allowed to modify the returned buffer pointer /// if an internal buffer is returned. -unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, +unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, const LangOptions &LangOpts, bool *Invalid) { assert((int)Tok.getLength() >= 0 && "Token character range is bogus!"); @@ -592,17 +604,17 @@ if (TheTok.getKind() == tok::eof) { break; } - +
[PATCH] D39279: Stringizing raw string literals containing newline
twoh updated this revision to Diff 125564. twoh added a comment. clang-format https://reviews.llvm.org/D39279 Files: include/clang/Lex/Lexer.h lib/Lex/Lexer.cpp test/Preprocessor/macro_raw_string.cpp unittests/Lex/LexerTest.cpp Index: unittests/Lex/LexerTest.cpp === --- unittests/Lex/LexerTest.cpp +++ unittests/Lex/LexerTest.cpp @@ -37,7 +37,7 @@ DiagID(new DiagnosticIDs()), Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), - TargetOpts(new TargetOptions) + TargetOpts(new TargetOptions) { TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); @@ -478,4 +478,42 @@ EXPECT_TRUE(LexedTokens.empty()); } +TEST_F(LexerTest, StringizingRasString) { + // For "std::string Lexer::Stringify(StringRef Str, bool Charify)". + std::string String1 = R"(foo +{"bar":[]} +baz)"; + // For "void Lexer::Stringify(SmallVectorImpl &Str)". + SmallString<128> String2; + String2 += String1.c_str(); + + // Corner cases. + std::string String3 = R"(\ +\n +\\n +\\)"; + SmallString<128> String4; + String4 += String3.c_str(); + std::string String5 = R"(a\ + + +\\b)"; + SmallString<128> String6; + String6 += String5.c_str(); + + String1 = Lexer::Stringify(StringRef(String1)); + Lexer::Stringify(String2); + String3 = Lexer::Stringify(StringRef(String3)); + Lexer::Stringify(String4); + String5 = Lexer::Stringify(StringRef(String5)); + Lexer::Stringify(String6); + + EXPECT_EQ(String1, R"(foo\n{\"bar\":[]}\nbaz)"); + EXPECT_EQ(String2, R"(foo\n{\"bar\":[]}\nbaz)"); + EXPECT_EQ(String3, R"(\\\n\\n\nn\n)"); + EXPECT_EQ(String4, R"(\\\n\\n\nn\n)"); + EXPECT_EQ(String5, R"(a\\\n\n\nb)"); + EXPECT_EQ(String6, R"(a\\\n\n\nb)"); +} + } // anonymous namespace Index: test/Preprocessor/macro_raw_string.cpp === --- /dev/null +++ test/Preprocessor/macro_raw_string.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -E -std=c++11 %s -o %t +// RUN: %clang_cc1 %t + +#define FOO(str) foo(#str) + +extern void foo(const char *str); + +void bar() { + FOO(R"(foo +bar)"); +} Index: lib/Lex/Lexer.cpp === --- lib/Lex/Lexer.cpp +++ lib/Lex/Lexer.cpp @@ -209,30 +209,39 @@ return L; } -/// Stringify - Convert the specified string into a C string, with surrounding -/// ""'s, and with escaped \ and " characters. +template void StringifyImpl(T &Str, char Quote) { + typename T::size_type i = 0, e = Str.size(); + while (i < e) { +if (Str[i] == '\\' || Str[i] == Quote) { + Str.insert(Str.begin() + i, '\\'); + i += 2; + ++e; +} else if (Str[i] == '\n' || Str[i] == '\r') { + // Replace '\r\n' and '\n\r' to '\\' followed by 'n'. + if ((i < e - 1) && (Str[i + 1] == '\n' || Str[i + 1] == '\r') && + Str[i] != Str[i + 1]) { +Str[i] = '\\'; +Str[i + 1] = 'n'; + } else { +// Replace '\n' and '\r' to '\\' followed by 'n'. +Str[i] = '\\'; +Str.insert(Str.begin() + i + 1, 'n'); +++e; + } + i += 2; +} else + ++i; + } +} + std::string Lexer::Stringify(StringRef Str, bool Charify) { std::string Result = Str; char Quote = Charify ? '\'' : '"'; - for (unsigned i = 0, e = Result.size(); i != e; ++i) { -if (Result[i] == '\\' || Result[i] == Quote) { - Result.insert(Result.begin()+i, '\\'); - ++i; ++e; -} - } + StringifyImpl(Result, Quote); return Result; } -/// Stringify - Convert the specified string into a C string by escaping '\' -/// and " characters. This does not add surrounding ""'s to the string. -void Lexer::Stringify(SmallVectorImpl &Str) { - for (unsigned i = 0, e = Str.size(); i != e; ++i) { -if (Str[i] == '\\' || Str[i] == '"') { - Str.insert(Str.begin()+i, '\\'); - ++i; ++e; -} - } -} +void Lexer::Stringify(SmallVectorImpl &Str) { StringifyImpl(Str, '"'); } //===--===// // Token Spelling @@ -367,7 +376,7 @@ /// to point to a constant buffer with the data already in it (avoiding a /// copy). The caller is not allowed to modify the returned buffer pointer /// if an internal buffer is returned. -unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, +unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, const LangOptions &LangOpts, bool *Invalid) { assert((int)Tok.getLength() >= 0 && "Token character range is bogus!"); @@ -592,17 +601,17 @@ if (TheTok.getKind() == tok::eof) { break; } - + // If we haven't hit the end of the
[PATCH] D39279: Stringizing raw string literals containing newline
This revision was automatically updated to reflect the committed changes. Closed by commit rC319904: Stringizing raw string literals containing newline (authored by twoh). Changed prior to commit: https://reviews.llvm.org/D39279?vs=125564&id=125745#toc Repository: rC Clang https://reviews.llvm.org/D39279 Files: include/clang/Lex/Lexer.h lib/Lex/Lexer.cpp test/Preprocessor/macro_raw_string.cpp unittests/Lex/LexerTest.cpp Index: lib/Lex/Lexer.cpp === --- lib/Lex/Lexer.cpp +++ lib/Lex/Lexer.cpp @@ -209,30 +209,39 @@ return L; } -/// Stringify - Convert the specified string into a C string, with surrounding -/// ""'s, and with escaped \ and " characters. +template void StringifyImpl(T &Str, char Quote) { + typename T::size_type i = 0, e = Str.size(); + while (i < e) { +if (Str[i] == '\\' || Str[i] == Quote) { + Str.insert(Str.begin() + i, '\\'); + i += 2; + ++e; +} else if (Str[i] == '\n' || Str[i] == '\r') { + // Replace '\r\n' and '\n\r' to '\\' followed by 'n'. + if ((i < e - 1) && (Str[i + 1] == '\n' || Str[i + 1] == '\r') && + Str[i] != Str[i + 1]) { +Str[i] = '\\'; +Str[i + 1] = 'n'; + } else { +// Replace '\n' and '\r' to '\\' followed by 'n'. +Str[i] = '\\'; +Str.insert(Str.begin() + i + 1, 'n'); +++e; + } + i += 2; +} else + ++i; + } +} + std::string Lexer::Stringify(StringRef Str, bool Charify) { std::string Result = Str; char Quote = Charify ? '\'' : '"'; - for (unsigned i = 0, e = Result.size(); i != e; ++i) { -if (Result[i] == '\\' || Result[i] == Quote) { - Result.insert(Result.begin()+i, '\\'); - ++i; ++e; -} - } + StringifyImpl(Result, Quote); return Result; } -/// Stringify - Convert the specified string into a C string by escaping '\' -/// and " characters. This does not add surrounding ""'s to the string. -void Lexer::Stringify(SmallVectorImpl &Str) { - for (unsigned i = 0, e = Str.size(); i != e; ++i) { -if (Str[i] == '\\' || Str[i] == '"') { - Str.insert(Str.begin()+i, '\\'); - ++i; ++e; -} - } -} +void Lexer::Stringify(SmallVectorImpl &Str) { StringifyImpl(Str, '"'); } //===--===// // Token Spelling @@ -367,7 +376,7 @@ /// to point to a constant buffer with the data already in it (avoiding a /// copy). The caller is not allowed to modify the returned buffer pointer /// if an internal buffer is returned. -unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, +unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, const LangOptions &LangOpts, bool *Invalid) { assert((int)Tok.getLength() >= 0 && "Token character range is bogus!"); @@ -592,17 +601,17 @@ if (TheTok.getKind() == tok::eof) { break; } - + // If we haven't hit the end of the preprocessor directive, skip this // token. if (!TheTok.isAtStartOfLine()) continue; - + // We've passed the end of the preprocessor directive, and will look // at this token again below. InPreprocessorDirective = false; } - + // Keep track of the # of lines in the preamble. if (TheTok.isAtStartOfLine()) { unsigned TokOffset = TheTok.getLocation().getRawEncoding() - StartOffset; @@ -619,13 +628,13 @@ ActiveCommentLoc = TheTok.getLocation(); continue; } - + if (TheTok.isAtStartOfLine() && TheTok.getKind() == tok::hash) { - // This is the start of a preprocessor directive. + // This is the start of a preprocessor directive. Token HashTok = TheTok; InPreprocessorDirective = true; ActiveCommentLoc = SourceLocation(); - + // Figure out which directive this is. Since we're lexing raw tokens, // we don't have an identifier table available. Instead, just look at // the raw identifier to recognize and categorize preprocessor directives. @@ -665,7 +674,7 @@ break; } } - + // We only end up here if we didn't recognize the preprocessor // directive or it was one that can't occur in the preamble at this // point. Roll back the current token to the location of the '#'. @@ -678,7 +687,7 @@ // the preamble. break; } while (true); - + SourceLocation End; if (ActiveCommentLoc.isValid()) End = ActiveCommentLoc; // don't truncate a decl comment. @@ -700,13 +709,13 @@ // trigraphs. bool Invalid = false; const char *TokPtr = SM.getCharacterData(TokStart, &Invalid); - + // If they request the first char of the token, we're trivially done. if (Invalid || (CharNo == 0 && Lexer::isObviouslySimpleCharacter(*TokPtr))) return TokStart; - +
[PATCH] D34796: upporting -f(no)-reorder-functions flag, clang side change
twoh added a comment. Ping. Thanks! https://reviews.llvm.org/D34796 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D34796: upporting -f(no)-reorder-functions flag, clang side change
twoh updated this revision to Diff 108967. twoh added a comment. Update documentation. Please let me know if I need to update other documents as well. Thanks! https://reviews.llvm.org/D34796 Files: docs/ClangCommandLineReference.rst include/clang/Driver/Options.td include/clang/Frontend/CodeGenOptions.def lib/CodeGen/BackendUtil.cpp lib/Driver/ToolChains/Clang.cpp lib/Frontend/CompilerInvocation.cpp test/CodeGen/Inputs/freorder-functions.prof test/CodeGen/freorder-functions.c test/Driver/function-sections.c Index: test/Driver/function-sections.c === --- test/Driver/function-sections.c +++ test/Driver/function-sections.c @@ -6,6 +6,8 @@ // CHECK-NODS-NOT: -fdata-sections // CHECK-US-NOT: -fno-unique-section-names // CHECK-NOUS: -fno-unique-section-names +// CHECK-RF-NOT: -fno-reorder-functions +// CHECK-NORF: -fno-reorder-functions // RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ // RUN: -target i386-unknown-linux \ @@ -72,3 +74,13 @@ // RUN: -target i386-unknown-linux \ // RUN: -fno-unique-section-names \ // RUN: | FileCheck --check-prefix=CHECK-NOUS %s + +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1\ +// RUN: -target i386-unknown-linux \ +// RUN: -freorder-functions \ +// RUN: | FileCheck --check-prefix=CHECK-RF %s + +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1\ +// RUN: -target i386-unknown-linux \ +// RUN: -fno-reorder-functions \ +// RUN: | FileCheck --check-prefix=CHECK-NORF %s Index: test/CodeGen/freorder-functions.c === --- /dev/null +++ test/CodeGen/freorder-functions.c @@ -0,0 +1,22 @@ +// REQUIRES: x86-registered-target + +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -o - < %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -fno-reorder-functions -o - < %s | FileCheck --check-prefix=CHECK-NOPREFIX %s + +// opt tool option precedes driver option. +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -fno-reorder-functions -mllvm -profile-guided-section-prefix=true -o - < %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -freorder-functions -mllvm -profile-guided-section-prefix=false -o - < %s | FileCheck --check-prefix=CHECK-NOPREFIX %s + +void hot_func() { + return; +} + +void cold_func() { + hot_func(); + return; +} + +// CHECK: .section .text.hot.hot_func,"ax",@progbits +// CHECK: .section .text.unlikely.cold_func,"ax",@progbits +// CHECK-NOPREFIX: .section .text.hot_func,"ax",@progbits +// CHECK-NOPREFIX: .section .text.cold_func,"ax",@progbits Index: test/CodeGen/Inputs/freorder-functions.prof === --- /dev/null +++ test/CodeGen/Inputs/freorder-functions.prof @@ -0,0 +1,5 @@ +hot_func:1000:0 + 1: 0 +cold_func:0:0 + 1: 1 + 2: 1 Index: lib/Frontend/CompilerInvocation.cpp === --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -647,6 +647,8 @@ OPT_fno_data_sections, false); Opts.UniqueSectionNames = Args.hasFlag(OPT_funique_section_names, OPT_fno_unique_section_names, true); + Opts.ReorderFunctions = + Args.hasFlag(OPT_freorder_functions, OPT_fno_reorder_functions, true); Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions); Index: lib/Driver/ToolChains/Clang.cpp === --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -2899,6 +2899,10 @@ options::OPT_fno_unique_section_names, true)) CmdArgs.push_back("-fno-unique-section-names"); + if (!Args.hasFlag(options::OPT_freorder_functions, +options::OPT_fno_reorder_functions, true)) +CmdArgs.push_back("-fno-reorder-functions"); + Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions); addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs); Index: lib/CodeGen/BackendUtil.cpp === --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -429,6 +429,7 @@ Options.FunctionSections = CodeGenOpts.FunctionSections; Options.DataSections = CodeGenOpts.DataSections; Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames; + Options.ReorderFunctions = CodeGenOpts.ReorderFunctions; Options.EmulatedTLS = CodeGenOpts.EmulatedTLS; Options.DebuggerTuning = CodeGenOpts.getDe
[PATCH] D34796: upporting -f(no)-reorder-functions flag, clang side change
twoh added a comment. I think it is generally good to match what GCC does to not to confuse people. https://reviews.llvm.org/D34796 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D36474: Use the file name from linemarker for debug info if an input is preprocessed source.
twoh created this revision. Herald added a subscriber: aprantl. Even in the case of the input file is a preprocessed source, clang uses the file name of the preprocesses source for debug info (DW_AT_name attribute for DW_TAG_compile_unit). However, gcc uses the file name specified in the first linemarker instead. This makes more sense because the one specified in the linemarker represents the "actual" source file name. Clang already uses the file name specified in the first linemarker for Module name (https://github.com/llvm-mirror/clang/blob/master/lib/Frontend/FrontendAction.cpp#L779) if the input is preprocessed. This patch makes clang to use the same value for debug info as well. https://reviews.llvm.org/D36474 Files: lib/CodeGen/CGDebugInfo.cpp test/CodeGen/debug-info-preprocessed-file.i Index: test/CodeGen/debug-info-preprocessed-file.i === --- /dev/null +++ test/CodeGen/debug-info-preprocessed-file.i @@ -0,0 +1,10 @@ +# 1 "/foo/bar/preprocessed-input.c" +# 1 "" 1 +# 1 "" 3 +# 318 "" 3 +# 1 "" 1 +# 1 "" 2 +# 1 "preprocessed-input.c" 2 + +// RUN: %clang -g -c -S -emit-llvm -o - %s | FileCheck %s +// CHECK: !DIFile(filename: "/foo/bar/preprocessed-input.c" Index: lib/CodeGen/CGDebugInfo.cpp === --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -28,6 +28,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" #include "clang/Frontend/CodeGenOptions.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PreprocessorOptions.h" @@ -484,6 +485,16 @@ MainFileName = MainFileDirSS.str(); } CSKind = computeChecksum(SM.getMainFileID(), Checksum); + +// If the main file name provided is identical to the input file name, and +// if the input file is a preprocessed source, use the module name for +// debug info. The module name comes from the name specified in the first +// linemarker if the input is a preprocessed source. +if (MainFile->getName() == MainFileName && +FrontendOptions::getInputKindForExtension( +MainFile->getName().rsplit('.').second) +.isPreprocessed()) + MainFileName = CGM.getModule().getName().str(); } llvm::dwarf::SourceLanguage LangTag; Index: test/CodeGen/debug-info-preprocessed-file.i === --- /dev/null +++ test/CodeGen/debug-info-preprocessed-file.i @@ -0,0 +1,10 @@ +# 1 "/foo/bar/preprocessed-input.c" +# 1 "" 1 +# 1 "" 3 +# 318 "" 3 +# 1 "" 1 +# 1 "" 2 +# 1 "preprocessed-input.c" 2 + +// RUN: %clang -g -c -S -emit-llvm -o - %s | FileCheck %s +// CHECK: !DIFile(filename: "/foo/bar/preprocessed-input.c" Index: lib/CodeGen/CGDebugInfo.cpp === --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -28,6 +28,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" #include "clang/Frontend/CodeGenOptions.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PreprocessorOptions.h" @@ -484,6 +485,16 @@ MainFileName = MainFileDirSS.str(); } CSKind = computeChecksum(SM.getMainFileID(), Checksum); + +// If the main file name provided is identical to the input file name, and +// if the input file is a preprocessed source, use the module name for +// debug info. The module name comes from the name specified in the first +// linemarker if the input is a preprocessed source. +if (MainFile->getName() == MainFileName && +FrontendOptions::getInputKindForExtension( +MainFile->getName().rsplit('.').second) +.isPreprocessed()) + MainFileName = CGM.getModule().getName().str(); } llvm::dwarf::SourceLanguage LangTag; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D36474: Use the file name from linemarker for debug info if an input is preprocessed source.
twoh updated this revision to Diff 110230. twoh added a comment. Relocate. https://reviews.llvm.org/D36474 Files: lib/CodeGen/CGDebugInfo.cpp test/CodeGen/debug-info-preprocessed-file.i Index: test/CodeGen/debug-info-preprocessed-file.i === --- /dev/null +++ test/CodeGen/debug-info-preprocessed-file.i @@ -0,0 +1,10 @@ +# 1 "/foo/bar/preprocessed-input.c" +# 1 "" 1 +# 1 "" 3 +# 318 "" 3 +# 1 "" 1 +# 1 "" 2 +# 1 "preprocessed-input.c" 2 + +// RUN: %clang -g -c -S -emit-llvm -o - %s | FileCheck %s +// CHECK: !DIFile(filename: "/foo/bar/preprocessed-input.c" Index: lib/CodeGen/CGDebugInfo.cpp === --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -28,6 +28,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" #include "clang/Frontend/CodeGenOptions.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PreprocessorOptions.h" @@ -483,6 +484,16 @@ llvm::sys::path::append(MainFileDirSS, MainFileName); MainFileName = MainFileDirSS.str(); } +// If the main file name provided is identical to the input file name, and +// if the input file is a preprocessed source, use the module name for +// debug info. The module name comes from the name specified in the first +// linemarker if the input is a preprocessed source. +if (MainFile->getName() == MainFileName && +FrontendOptions::getInputKindForExtension( +MainFile->getName().rsplit('.').second) +.isPreprocessed()) + MainFileName = CGM.getModule().getName().str(); + CSKind = computeChecksum(SM.getMainFileID(), Checksum); } Index: test/CodeGen/debug-info-preprocessed-file.i === --- /dev/null +++ test/CodeGen/debug-info-preprocessed-file.i @@ -0,0 +1,10 @@ +# 1 "/foo/bar/preprocessed-input.c" +# 1 "" 1 +# 1 "" 3 +# 318 "" 3 +# 1 "" 1 +# 1 "" 2 +# 1 "preprocessed-input.c" 2 + +// RUN: %clang -g -c -S -emit-llvm -o - %s | FileCheck %s +// CHECK: !DIFile(filename: "/foo/bar/preprocessed-input.c" Index: lib/CodeGen/CGDebugInfo.cpp === --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -28,6 +28,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" #include "clang/Frontend/CodeGenOptions.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PreprocessorOptions.h" @@ -483,6 +484,16 @@ llvm::sys::path::append(MainFileDirSS, MainFileName); MainFileName = MainFileDirSS.str(); } +// If the main file name provided is identical to the input file name, and +// if the input file is a preprocessed source, use the module name for +// debug info. The module name comes from the name specified in the first +// linemarker if the input is a preprocessed source. +if (MainFile->getName() == MainFileName && +FrontendOptions::getInputKindForExtension( +MainFile->getName().rsplit('.').second) +.isPreprocessed()) + MainFileName = CGM.getModule().getName().str(); + CSKind = computeChecksum(SM.getMainFileID(), Checksum); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D36474: Use the file name from linemarker for debug info if an input is preprocessed source.
twoh updated this revision to Diff 110237. twoh added a comment. Addressing dblaikie's comments. Thanks! https://reviews.llvm.org/D36474 Files: lib/CodeGen/CGDebugInfo.cpp test/CodeGen/debug-info-preprocessed-file.i Index: test/CodeGen/debug-info-preprocessed-file.i === --- /dev/null +++ test/CodeGen/debug-info-preprocessed-file.i @@ -0,0 +1,11 @@ +# 1 "/foo/bar/preprocessed-input.c" +# 1 "" 1 +# 1 "" 3 +# 318 "" 3 +# 1 "" 1 +# 1 "" 2 +# 1 "preprocessed-input.c" 2 + +// RUN: %clang -g -c -S -emit-llvm -o - %s | FileCheck %s +// CHECK: !DICompileUnit(language: DW_LANG_C99, file: ![[FILE:[0-9]+]] +// CHECK: ![[FILE]] = !DIFile(filename: "/foo/bar/preprocessed-input.c" Index: lib/CodeGen/CGDebugInfo.cpp === --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -28,6 +28,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" #include "clang/Frontend/CodeGenOptions.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PreprocessorOptions.h" @@ -483,6 +484,16 @@ llvm::sys::path::append(MainFileDirSS, MainFileName); MainFileName = MainFileDirSS.str(); } +// If the main file name provided is identical to the input file name, and +// if the input file is a preprocessed source, use the module name for +// debug info. The module name comes from the name specified in the first +// linemarker if the input is a preprocessed source. +if (MainFile->getName() == MainFileName && +FrontendOptions::getInputKindForExtension( +MainFile->getName().rsplit('.').second) +.isPreprocessed()) + MainFileName = CGM.getModule().getName().str(); + CSKind = computeChecksum(SM.getMainFileID(), Checksum); } Index: test/CodeGen/debug-info-preprocessed-file.i === --- /dev/null +++ test/CodeGen/debug-info-preprocessed-file.i @@ -0,0 +1,11 @@ +# 1 "/foo/bar/preprocessed-input.c" +# 1 "" 1 +# 1 "" 3 +# 318 "" 3 +# 1 "" 1 +# 1 "" 2 +# 1 "preprocessed-input.c" 2 + +// RUN: %clang -g -c -S -emit-llvm -o - %s | FileCheck %s +// CHECK: !DICompileUnit(language: DW_LANG_C99, file: ![[FILE:[0-9]+]] +// CHECK: ![[FILE]] = !DIFile(filename: "/foo/bar/preprocessed-input.c" Index: lib/CodeGen/CGDebugInfo.cpp === --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -28,6 +28,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" #include "clang/Frontend/CodeGenOptions.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PreprocessorOptions.h" @@ -483,6 +484,16 @@ llvm::sys::path::append(MainFileDirSS, MainFileName); MainFileName = MainFileDirSS.str(); } +// If the main file name provided is identical to the input file name, and +// if the input file is a preprocessed source, use the module name for +// debug info. The module name comes from the name specified in the first +// linemarker if the input is a preprocessed source. +if (MainFile->getName() == MainFileName && +FrontendOptions::getInputKindForExtension( +MainFile->getName().rsplit('.').second) +.isPreprocessed()) + MainFileName = CGM.getModule().getName().str(); + CSKind = computeChecksum(SM.getMainFileID(), Checksum); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D36474: Use the file name from linemarker for debug info if an input is preprocessed source.
twoh added a comment. Ping. Thanks! https://reviews.llvm.org/D36474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D34796: upporting -f(no)-reorder-functions flag, clang side change
twoh added a comment. Friendly ping. @davidxl, I think there's no harm to make clang consistent with gcc for compiler options, and I wonder if you have any concerns that I may miss. Thanks! https://reviews.llvm.org/D34796 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D36474: Use the file name from linemarker for debug info if an input is preprocessed source.
This revision was automatically updated to reflect the committed changes. Closed by commit rL311037: Use the file name from linemarker for debug info if an input is preprocessed… (authored by twoh). Repository: rL LLVM https://reviews.llvm.org/D36474 Files: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp cfe/trunk/test/CodeGen/debug-info-preprocessed-file.i Index: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp === --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp @@ -29,6 +29,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" #include "clang/Frontend/CodeGenOptions.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PreprocessorOptions.h" @@ -495,6 +496,16 @@ llvm::sys::path::append(MainFileDirSS, MainFileName); MainFileName = MainFileDirSS.str(); } +// If the main file name provided is identical to the input file name, and +// if the input file is a preprocessed source, use the module name for +// debug info. The module name comes from the name specified in the first +// linemarker if the input is a preprocessed source. +if (MainFile->getName() == MainFileName && +FrontendOptions::getInputKindForExtension( +MainFile->getName().rsplit('.').second) +.isPreprocessed()) + MainFileName = CGM.getModule().getName().str(); + CSKind = computeChecksum(SM.getMainFileID(), Checksum); } Index: cfe/trunk/test/CodeGen/debug-info-preprocessed-file.i === --- cfe/trunk/test/CodeGen/debug-info-preprocessed-file.i +++ cfe/trunk/test/CodeGen/debug-info-preprocessed-file.i @@ -0,0 +1,11 @@ +# 1 "/foo/bar/preprocessed-input.c" +# 1 "" 1 +# 1 "" 3 +# 318 "" 3 +# 1 "" 1 +# 1 "" 2 +# 1 "preprocessed-input.c" 2 + +// RUN: %clang -g -c -S -emit-llvm -o - %s | FileCheck %s +// CHECK: !DICompileUnit(language: DW_LANG_C99, file: ![[FILE:[0-9]+]] +// CHECK: ![[FILE]] = !DIFile(filename: "/foo/bar/preprocessed-input.c" Index: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp === --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp @@ -29,6 +29,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" #include "clang/Frontend/CodeGenOptions.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PreprocessorOptions.h" @@ -495,6 +496,16 @@ llvm::sys::path::append(MainFileDirSS, MainFileName); MainFileName = MainFileDirSS.str(); } +// If the main file name provided is identical to the input file name, and +// if the input file is a preprocessed source, use the module name for +// debug info. The module name comes from the name specified in the first +// linemarker if the input is a preprocessed source. +if (MainFile->getName() == MainFileName && +FrontendOptions::getInputKindForExtension( +MainFile->getName().rsplit('.').second) +.isPreprocessed()) + MainFileName = CGM.getModule().getName().str(); + CSKind = computeChecksum(SM.getMainFileID(), Checksum); } Index: cfe/trunk/test/CodeGen/debug-info-preprocessed-file.i === --- cfe/trunk/test/CodeGen/debug-info-preprocessed-file.i +++ cfe/trunk/test/CodeGen/debug-info-preprocessed-file.i @@ -0,0 +1,11 @@ +# 1 "/foo/bar/preprocessed-input.c" +# 1 "" 1 +# 1 "" 3 +# 318 "" 3 +# 1 "" 1 +# 1 "" 2 +# 1 "preprocessed-input.c" 2 + +// RUN: %clang -g -c -S -emit-llvm -o - %s | FileCheck %s +// CHECK: !DICompileUnit(language: DW_LANG_C99, file: ![[FILE:[0-9]+]] +// CHECK: ![[FILE]] = !DIFile(filename: "/foo/bar/preprocessed-input.c" ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D103745: [dfsan] Add full fast8 support
twoh added a comment. @gbalats @stephan.yichao.zhao Hello sorry for the late comment but I wonder what was the reason behind this change (changing taint label representation from 16-bit to 8-bit-fast only). Do we have any discussion thread from llvm-dev regarding this? Thanks! Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D103745/new/ https://reviews.llvm.org/D103745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D103745: [dfsan] Add full fast8 support
twoh added a comment. @browneee Thanks for the reply! IIUC, with non-fast mode and 16-bit shadow data, it could support 2^16 labels with a single run, so the coverage reduction is 2^16 -> 8. Do I miss something? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D103745/new/ https://reviews.llvm.org/D103745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D103745: [dfsan] Add full fast8 support
twoh added a comment. @browneee Thanks! Makes sense. Is there a chance that you have an idea of the ballpark overhead of the legacy mode? I'm curious if we track N-labels, the total CPU time is generally much higher with "legacy-mode single-run with N labels" than "fast-8 mode (N/8) runs". I think there are still reasons to prefer multiple runs of fast-8 mode over the legacy mode even when the total CPU times are similar, but I wonder how bad is the overhead of expensive union operations performed by the legacy mode. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D103745/new/ https://reviews.llvm.org/D103745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D39279: Stringizing raw string literals containing newline
twoh added a comment. Ping. Thanks! https://reviews.llvm.org/D39279 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D39279: Stringizing raw string literals containing newline
twoh updated this revision to Diff 123658. twoh added a comment. Addressing @vsapsai's comments. Thank you for the suggestion! Added test case actually finds an off-by-one error in the original patch. I improved the comments as well. https://reviews.llvm.org/D39279 Files: include/clang/Lex/Lexer.h lib/Lex/Lexer.cpp test/Preprocessor/macro_raw_string.cpp unittests/Lex/LexerTest.cpp Index: unittests/Lex/LexerTest.cpp === --- unittests/Lex/LexerTest.cpp +++ unittests/Lex/LexerTest.cpp @@ -37,7 +37,7 @@ DiagID(new DiagnosticIDs()), Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), - TargetOpts(new TargetOptions) + TargetOpts(new TargetOptions) { TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); @@ -478,4 +478,42 @@ EXPECT_TRUE(LexedTokens.empty()); } +TEST_F(LexerTest, StringizingRasString) { + // For "std::string Lexer::Stringify(StringRef Str, bool Charify)". + std::string String1 = R"(foo +{"bar":[]} +baz)"; + // For "void Lexer::Stringify(SmallVectorImpl &Str)". + SmallString<128> String2; + String2 += String1.c_str(); + + // Corner cases. + std::string String3 = R"(\ +\n +\\n +\\)"; + SmallString<128> String4; + String4 += String3.c_str(); + std::string String5 = R"(a\ + + +\\b)"; + SmallString<128> String6; + String6 += String5.c_str(); + + String1 = Lexer::Stringify(StringRef(String1)); + Lexer::Stringify(String2); + String3 = Lexer::Stringify(StringRef(String3)); + Lexer::Stringify(String4); + String5 = Lexer::Stringify(StringRef(String5)); + Lexer::Stringify(String6); + + EXPECT_EQ(String1, R"(foo\n{\"bar\":[]}\nbaz)"); + EXPECT_EQ(String2, R"(foo\n{\"bar\":[]}\nbaz)"); + EXPECT_EQ(String3, R"(\\\n\\n\nn\n)"); + EXPECT_EQ(String4, R"(\\\n\\n\nn\n)"); + EXPECT_EQ(String5, R"(a\\\n\n\nb)"); + EXPECT_EQ(String6, R"(a\\\n\n\nb)"); +} + } // anonymous namespace Index: test/Preprocessor/macro_raw_string.cpp === --- /dev/null +++ test/Preprocessor/macro_raw_string.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -E -std=c++11 %s -o %t +// RUN: %clang_cc1 %t + +#define FOO(str) foo(#str) + +extern void foo(const char *str); + +void bar() { + FOO(R"(foo +bar)"); +} Index: lib/Lex/Lexer.cpp === --- lib/Lex/Lexer.cpp +++ lib/Lex/Lexer.cpp @@ -209,29 +209,43 @@ return L; } -/// Stringify - Convert the specified string into a C string, with surrounding -/// ""'s, and with escaped \ and " characters. +/// StringifyImpl - Implementation of Stringify functions. Convert the +/// specified string into a C string by i) escaping '\' and " characters and +/// ii) replacing newline character(s) with "\n". +template +void StringifyImpl(T& Str, char Quote) { + unsigned i = 0, e = Str.size(); + while (i < e) { +if (Str[i] == '\\' || Str[i] == Quote) { + Str.insert(Str.begin() + i, '\\'); + i += 2; + ++e; +} else if (Str[i] == '\n' || Str[i] == '\r') { + // Replace '\n', '\r', '\r\n', and '\n\r' to '\\' followed by 'n'. + unsigned Size = 1; + if ((i < e - 1) && (Str[i + 1] == '\n' || Str[i + 1] == '\r') && + Str[i] != Str[i + 1]) +Size += 1; + + Str.erase(Str.begin() + i, Str.begin() + i + Size); + Str.insert(Str.begin() + i, '\\'); + Str.insert(Str.begin() + i + 1, 'n'); + i += 2; + e += (2 - Size); +} else + ++i; + } +} + std::string Lexer::Stringify(StringRef Str, bool Charify) { std::string Result = Str; char Quote = Charify ? '\'' : '"'; - for (unsigned i = 0, e = Result.size(); i != e; ++i) { -if (Result[i] == '\\' || Result[i] == Quote) { - Result.insert(Result.begin()+i, '\\'); - ++i; ++e; -} - } + StringifyImpl(Result, Quote); return Result; } -/// Stringify - Convert the specified string into a C string by escaping '\' -/// and " characters. This does not add surrounding ""'s to the string. void Lexer::Stringify(SmallVectorImpl &Str) { - for (unsigned i = 0, e = Str.size(); i != e; ++i) { -if (Str[i] == '\\' || Str[i] == '"') { - Str.insert(Str.begin()+i, '\\'); - ++i; ++e; -} - } + StringifyImpl(Str, '"'); } //===--===// @@ -367,7 +381,7 @@ /// to point to a constant buffer with the data already in it (avoiding a /// copy). The caller is not allowed to modify the returned buffer pointer /// if an internal buffer is returned. -unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, +unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr,
[PATCH] D34796: upporting -f(no)-reorder-functions flag, clang side change
twoh created this revision. When profile data is given, .hot/.unlikely section prefix is added to hot/cold functions for linker to improve code locality. GCC controls this behavior with '-f(no)-reorder-functions' flag, while LLVM uses opt tool option '-profile-guided-section-prefix=true/false'. This patch is for LLVM to support the same driver flag with GCC. LLVM side patch is https://reviews.llvm.org/D34795. https://reviews.llvm.org/D34796 Files: include/clang/Driver/Options.td include/clang/Frontend/CodeGenOptions.def lib/CodeGen/BackendUtil.cpp lib/Driver/ToolChains/Clang.cpp lib/Frontend/CompilerInvocation.cpp test/CodeGen/Inputs/freorder-functions.prof test/CodeGen/freorder-functions.c test/Driver/function-sections.c Index: test/Driver/function-sections.c === --- test/Driver/function-sections.c +++ test/Driver/function-sections.c @@ -6,6 +6,8 @@ // CHECK-NODS-NOT: -fdata-sections // CHECK-US-NOT: -fno-unique-section-names // CHECK-NOUS: -fno-unique-section-names +// CHECK-RF-NOT: -fno-reorder-functions +// CHECK-NORF: -fno-reorder-functions // RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ // RUN: -target i386-unknown-linux \ @@ -72,3 +74,13 @@ // RUN: -target i386-unknown-linux \ // RUN: -fno-unique-section-names \ // RUN: | FileCheck --check-prefix=CHECK-NOUS %s + +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1\ +// RUN: -target i386-unknown-linux \ +// RUN: -freorder-functions \ +// RUN: | FileCheck --check-prefix=CHECK-RF %s + +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1\ +// RUN: -target i386-unknown-linux \ +// RUN: -fno-reorder-functions \ +// RUN: | FileCheck --check-prefix=CHECK-NORF %s Index: test/CodeGen/freorder-functions.c === --- /dev/null +++ test/CodeGen/freorder-functions.c @@ -0,0 +1,22 @@ +// REQUIRES: x86-registered-target + +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -o - < %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -fno-reorder-functions -o - < %s | FileCheck --check-prefix=CHECK-NOPREFIX %s + +// opt tool option precedes driver option. +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -fno-reorder-functions -mllvm -profile-guided-section-prefix=true -o - < %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -freorder-functions -mllvm -profile-guided-section-prefix=false -o - < %s | FileCheck --check-prefix=CHECK-NOPREFIX %s + +void hot_func() { + return; +} + +void cold_func() { + hot_func(); + return; +} + +// CHECK: .section .text.hot.hot_func,"ax",@progbits +// CHECK: .section .text.unlikely.cold_func,"ax",@progbits +// CHECK-NOPREFIX: .section .text.hot_func,"ax",@progbits +// CHECK-NOPREFIX: .section .text.cold_func,"ax",@progbits Index: test/CodeGen/Inputs/freorder-functions.prof === --- /dev/null +++ test/CodeGen/Inputs/freorder-functions.prof @@ -0,0 +1,5 @@ +hot_func:1000:0 + 1: 0 +cold_func:0:0 + 1: 1 + 2: 1 Index: lib/Frontend/CompilerInvocation.cpp === --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -643,6 +643,8 @@ OPT_fno_data_sections, false); Opts.UniqueSectionNames = Args.hasFlag(OPT_funique_section_names, OPT_fno_unique_section_names, true); + Opts.ReorderFunctions = + Args.hasFlag(OPT_freorder_functions, OPT_fno_reorder_functions, true); Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions); Index: lib/Driver/ToolChains/Clang.cpp === --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -2861,6 +2861,10 @@ options::OPT_fno_unique_section_names, true)) CmdArgs.push_back("-fno-unique-section-names"); + if (!Args.hasFlag(options::OPT_freorder_functions, +options::OPT_fno_reorder_functions, true)) +CmdArgs.push_back("-fno-reorder-functions"); + Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions); addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs); Index: lib/CodeGen/BackendUtil.cpp === --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -431,6 +431,7 @@ Options.FunctionSections = CodeGenOpts.FunctionSections; Options.DataSections = CodeGenOpts.DataSections;
[PATCH] D30000: Fix for pr31836 - pp_nonportable_path on absolute paths: broken delimiters
twoh created this revision. This is a patch for PR31836. As the bug replaces the path separators in the included file name with the characters following them, the test script makes sure that there's no "Ccase-insensitive-include-pr31836.h" in the warning message. https://reviews.llvm.org/D3 Files: lib/Lex/PPDirectives.cpp test/Lexer/case-insensitive-include-pr31836.sh Index: test/Lexer/case-insensitive-include-pr31836.sh === --- /dev/null +++ test/Lexer/case-insensitive-include-pr31836.sh @@ -0,0 +1,9 @@ +// REQUIRES: case-insensitive-filesystem + +// RUN: mkdir -p %T +// RUN: touch %T/case-insensitive-include-pr31836.h +// RUN: echo "#include \"%T/Case-Insensitive-Include-Pr31836.h\"" | %clang_cc1 -E - 2>&1 | FileCheck %s + +// CHECK: warning: non-portable path to file +// CHECK-NOT: Ccase-insensitive-include-pr31836.h +// CHECK: {{$}} Index: lib/Lex/PPDirectives.cpp === --- lib/Lex/PPDirectives.cpp +++ lib/Lex/PPDirectives.cpp @@ -1976,8 +1976,12 @@ SmallString<128> Path; Path.reserve(Name.size()+2); Path.push_back(isAngled ? '<' : '"'); + bool isLeadingSeparator = llvm::sys::path::is_absolute(Name); for (auto Component : Components) { -Path.append(Component); +if (isLeadingSeparator) + isLeadingSeparator = false; +else + Path.append(Component); // Append the separator the user used, or the close quote Path.push_back( Path.size() <= Filename.size() ? Filename[Path.size()-1] : Index: test/Lexer/case-insensitive-include-pr31836.sh === --- /dev/null +++ test/Lexer/case-insensitive-include-pr31836.sh @@ -0,0 +1,9 @@ +// REQUIRES: case-insensitive-filesystem + +// RUN: mkdir -p %T +// RUN: touch %T/case-insensitive-include-pr31836.h +// RUN: echo "#include \"%T/Case-Insensitive-Include-Pr31836.h\"" | %clang_cc1 -E - 2>&1 | FileCheck %s + +// CHECK: warning: non-portable path to file +// CHECK-NOT: Ccase-insensitive-include-pr31836.h +// CHECK: {{$}} Index: lib/Lex/PPDirectives.cpp === --- lib/Lex/PPDirectives.cpp +++ lib/Lex/PPDirectives.cpp @@ -1976,8 +1976,12 @@ SmallString<128> Path; Path.reserve(Name.size()+2); Path.push_back(isAngled ? '<' : '"'); + bool isLeadingSeparator = llvm::sys::path::is_absolute(Name); for (auto Component : Components) { -Path.append(Component); +if (isLeadingSeparator) + isLeadingSeparator = false; +else + Path.append(Component); // Append the separator the user used, or the close quote Path.push_back( Path.size() <= Filename.size() ? Filename[Path.size()-1] : ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30000: Fix for pr31836 - pp_nonportable_path on absolute paths: broken delimiters
twoh updated this revision to Diff 88584. twoh added a comment. Make it explicit that the test doesn't support windows. @eric_niebler, my original intention was avoiding use of platform-dependent path separator, but now made it explicit that the test is not for windows, it should be okay to use '/'. Thanks for the comments! https://reviews.llvm.org/D3 Files: lib/Lex/PPDirectives.cpp test/Lexer/case-insensitive-include-pr31836.sh Index: test/Lexer/case-insensitive-include-pr31836.sh === --- /dev/null +++ test/Lexer/case-insensitive-include-pr31836.sh @@ -0,0 +1,9 @@ +// REQUIRES: case-insensitive-filesystem +// UNSUPPORTED: system-windows + +// RUN: mkdir -p %T +// RUN: touch %T/case-insensitive-include-pr31836.h +// RUN: echo "#include \"%T/Case-Insensitive-Include-Pr31836.h\"" | %clang_cc1 -E - 2>&1 | FileCheck %s + +// CHECK: warning: non-portable path to file +// CHECK-SAME: /case-insensitive-include-pr31836.h Index: lib/Lex/PPDirectives.cpp === --- lib/Lex/PPDirectives.cpp +++ lib/Lex/PPDirectives.cpp @@ -1976,8 +1976,12 @@ SmallString<128> Path; Path.reserve(Name.size()+2); Path.push_back(isAngled ? '<' : '"'); + bool isLeadingSeparator = llvm::sys::path::is_absolute(Name); for (auto Component : Components) { -Path.append(Component); +if (isLeadingSeparator) + isLeadingSeparator = false; +else + Path.append(Component); // Append the separator the user used, or the close quote Path.push_back( Path.size() <= Filename.size() ? Filename[Path.size()-1] : Index: test/Lexer/case-insensitive-include-pr31836.sh === --- /dev/null +++ test/Lexer/case-insensitive-include-pr31836.sh @@ -0,0 +1,9 @@ +// REQUIRES: case-insensitive-filesystem +// UNSUPPORTED: system-windows + +// RUN: mkdir -p %T +// RUN: touch %T/case-insensitive-include-pr31836.h +// RUN: echo "#include \"%T/Case-Insensitive-Include-Pr31836.h\"" | %clang_cc1 -E - 2>&1 | FileCheck %s + +// CHECK: warning: non-portable path to file +// CHECK-SAME: /case-insensitive-include-pr31836.h Index: lib/Lex/PPDirectives.cpp === --- lib/Lex/PPDirectives.cpp +++ lib/Lex/PPDirectives.cpp @@ -1976,8 +1976,12 @@ SmallString<128> Path; Path.reserve(Name.size()+2); Path.push_back(isAngled ? '<' : '"'); + bool isLeadingSeparator = llvm::sys::path::is_absolute(Name); for (auto Component : Components) { -Path.append(Component); +if (isLeadingSeparator) + isLeadingSeparator = false; +else + Path.append(Component); // Append the separator the user used, or the close quote Path.push_back( Path.size() <= Filename.size() ? Filename[Path.size()-1] : ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30000: Fix for pr31836 - pp_nonportable_path on absolute paths: broken delimiters
twoh added a comment. @eric_niebler I just tried it on Windows machine, and it just succeeded with no warnings/fix-it. Is that expected? https://reviews.llvm.org/D3 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30000: Fix for pr31836 - pp_nonportable_path on absolute paths: broken delimiters
twoh added inline comments. Comment at: test/Lexer/case-insensitive-include-pr31836.sh:6 +// RUN: touch %T/case-insensitive-include-pr31836.h +// RUN: echo "#include \"%T/Case-Insensitive-Include-Pr31836.h\"" | %clang_cc1 -E - 2>&1 | FileCheck %s + karies wrote: > @twoh Does that actually work on Linux? I thought (most?) Linux file systems > are case sensitive? I.e. I'd expect to get a "file not found" diag on the > `#include`. This is an unsupported test on Linux because of REQUIRES: case-insensitive-filesystem. https://reviews.llvm.org/D3 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30000: Fix for pr31836 - pp_nonportable_path on absolute paths: broken delimiters
twoh added a comment. @eric_niebler Do you want any more experiments with this patch? I think Windows machines not printing warnings/fixits for absolute path is a separate issue with this. https://reviews.llvm.org/D3 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30000: Fix for pr31836 - pp_nonportable_path on absolute paths: broken delimiters
This revision was automatically updated to reflect the committed changes. Closed by commit rL295779: Fix for pr31836 - pp_nonportable_path on absolute paths: broken delimiters (authored by twoh). Changed prior to commit: https://reviews.llvm.org/D3?vs=88584&id=89285#toc Repository: rL LLVM https://reviews.llvm.org/D3 Files: cfe/trunk/lib/Lex/PPDirectives.cpp cfe/trunk/test/Lexer/case-insensitive-include-pr31836.sh Index: cfe/trunk/lib/Lex/PPDirectives.cpp === --- cfe/trunk/lib/Lex/PPDirectives.cpp +++ cfe/trunk/lib/Lex/PPDirectives.cpp @@ -1976,8 +1976,12 @@ SmallString<128> Path; Path.reserve(Name.size()+2); Path.push_back(isAngled ? '<' : '"'); + bool isLeadingSeparator = llvm::sys::path::is_absolute(Name); for (auto Component : Components) { -Path.append(Component); +if (isLeadingSeparator) + isLeadingSeparator = false; +else + Path.append(Component); // Append the separator the user used, or the close quote Path.push_back( Path.size() <= Filename.size() ? Filename[Path.size()-1] : Index: cfe/trunk/test/Lexer/case-insensitive-include-pr31836.sh === --- cfe/trunk/test/Lexer/case-insensitive-include-pr31836.sh +++ cfe/trunk/test/Lexer/case-insensitive-include-pr31836.sh @@ -0,0 +1,9 @@ +// REQUIRES: case-insensitive-filesystem +// UNSUPPORTED: system-windows + +// RUN: mkdir -p %T +// RUN: touch %T/case-insensitive-include-pr31836.h +// RUN: echo "#include \"%T/Case-Insensitive-Include-Pr31836.h\"" | %clang_cc1 -E - 2>&1 | FileCheck %s + +// CHECK: warning: non-portable path to file +// CHECK-SAME: /case-insensitive-include-pr31836.h Index: cfe/trunk/lib/Lex/PPDirectives.cpp === --- cfe/trunk/lib/Lex/PPDirectives.cpp +++ cfe/trunk/lib/Lex/PPDirectives.cpp @@ -1976,8 +1976,12 @@ SmallString<128> Path; Path.reserve(Name.size()+2); Path.push_back(isAngled ? '<' : '"'); + bool isLeadingSeparator = llvm::sys::path::is_absolute(Name); for (auto Component : Components) { -Path.append(Component); +if (isLeadingSeparator) + isLeadingSeparator = false; +else + Path.append(Component); // Append the separator the user used, or the close quote Path.push_back( Path.size() <= Filename.size() ? Filename[Path.size()-1] : Index: cfe/trunk/test/Lexer/case-insensitive-include-pr31836.sh === --- cfe/trunk/test/Lexer/case-insensitive-include-pr31836.sh +++ cfe/trunk/test/Lexer/case-insensitive-include-pr31836.sh @@ -0,0 +1,9 @@ +// REQUIRES: case-insensitive-filesystem +// UNSUPPORTED: system-windows + +// RUN: mkdir -p %T +// RUN: touch %T/case-insensitive-include-pr31836.h +// RUN: echo "#include \"%T/Case-Insensitive-Include-Pr31836.h\"" | %clang_cc1 -E - 2>&1 | FileCheck %s + +// CHECK: warning: non-portable path to file +// CHECK-SAME: /case-insensitive-include-pr31836.h ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30591: Introduce the feature "linux" for tests only for linux
twoh created this revision. This feature is needed to re-enable https://reviews.llvm.org/rL293004, which resembles gcc's behavior in finding the input file name from a preprocessed source. The patch has been reverted in https://reviews.llvm.org/rL293032, because the test checks FILE symbol of ELF file, which is not valid on OSes not using ELF. With the patch, we can add "REQUIRES: linux" to the tests on ELF files, or tests that require any linux-specific features. https://reviews.llvm.org/D30591 Files: test/lit.cfg Index: test/lit.cfg === --- test/lit.cfg +++ test/lit.cfg @@ -427,6 +427,10 @@ if not re.match(r'.*-(cygwin)$', config.target_triple): config.available_features.add('clang-driver') +# Set on linux environment +if re.match(r'.*-linux', config.target_triple): +config.available_features.add("linux") + # [PR18856] Depends to remove opened file. On win32, a file could be removed # only if all handles were closed. if platform.system() not in ['Windows']: Index: test/lit.cfg === --- test/lit.cfg +++ test/lit.cfg @@ -427,6 +427,10 @@ if not re.match(r'.*-(cygwin)$', config.target_triple): config.available_features.add('clang-driver') +# Set on linux environment +if re.match(r'.*-linux', config.target_triple): +config.available_features.add("linux") + # [PR18856] Depends to remove opened file. On win32, a file could be removed # only if all handles were closed. if platform.system() not in ['Windows']: ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30591: Introduce the feature "linux" for tests only for linux
twoh abandoned this revision. twoh added a comment. @inglorion That makes a lot of sense. Maybe we don't even need -g, because -S -emit-llvm shows source_filename. I'll run some more experiments with relpath/abspath and debug locations, and submit a revised patch. Thanks for the comment! https://reviews.llvm.org/D30591 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30663: Use filename in linemarker when compiling preprocessed source (Revised)
twoh created this revision. This is a revised version of https://reviews.llvm.org/D28796. Included test is changed to resolve the target compatibility issue reported (https://reviews.llvm.org/rL293032). https://reviews.llvm.org/D30663 Files: include/clang/Frontend/FrontendOptions.h lib/Frontend/FrontendAction.cpp test/Frontend/preprocessed-input.c Index: test/Frontend/preprocessed-input.c === --- /dev/null +++ test/Frontend/preprocessed-input.c @@ -0,0 +1,3 @@ +// RUN: %clang -E -o %t.i %s +// RUN: %clang -emit-llvm -S -o - %t.i | FileCheck %s +// CHECK: source_filename = {{.*}}preprocessed-input.c"{{$}} Index: lib/Frontend/FrontendAction.cpp === --- lib/Frontend/FrontendAction.cpp +++ lib/Frontend/FrontendAction.cpp @@ -19,6 +19,7 @@ #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Parse/ParseAST.h" @@ -187,6 +188,42 @@ return llvm::make_unique(std::move(Consumers)); } +// For preprocessed files, if the first line is the linemarker and specifies +// the original source file name, use that name as the input file name. +static bool ReadOriginalFileName(CompilerInstance &CI, std::string &InputFile) +{ + bool Invalid = false; + auto &SourceMgr = CI.getSourceManager(); + auto MainFileID = SourceMgr.getMainFileID(); + const auto *MainFileBuf = SourceMgr.getBuffer(MainFileID, &Invalid); + if (Invalid) +return false; + + std::unique_ptr RawLexer( + new Lexer(MainFileID, MainFileBuf, SourceMgr, CI.getLangOpts())); + + // If the first line has the syntax of + // + // # NUM "FILENAME" + // + // we use FILENAME as the input file name. + Token T; + if (RawLexer->LexFromRawLexer(T) || T.getKind() != tok::hash) +return false; + if (RawLexer->LexFromRawLexer(T) || T.isAtStartOfLine() || + T.getKind() != tok::numeric_constant) +return false; + RawLexer->LexFromRawLexer(T); + if (T.isAtStartOfLine() || T.getKind() != tok::string_literal) +return false; + + StringLiteralParser Literal(T, CI.getPreprocessor()); + if (Literal.hadError) +return false; + InputFile = Literal.GetString().str(); + return true; +} + bool FrontendAction::BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input) { assert(!Instance && "Already processing a source file!"); @@ -338,6 +375,13 @@ if (!isModelParsingAction()) CI.createASTContext(); +// For preprocessed files, check if the first line specifies the original +// source file name with a linemarker. +std::string OrigFile; +if (Input.isPreprocessed()) + if (ReadOriginalFileName(CI, OrigFile)) +InputFile = OrigFile; + std::unique_ptr Consumer = CreateWrappedASTConsumer(CI, InputFile); if (!Consumer) @@ -430,9 +474,9 @@ // If there is a layout overrides file, attach an external AST source that // provides the layouts from that file. - if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && + if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { -IntrusiveRefCntPtr +IntrusiveRefCntPtr Override(new LayoutOverrideSource( CI.getFrontendOpts().OverrideRecordLayoutsFile)); CI.getASTContext().setExternalSource(Override); Index: include/clang/Frontend/FrontendOptions.h === --- include/clang/Frontend/FrontendOptions.h +++ include/clang/Frontend/FrontendOptions.h @@ -81,7 +81,7 @@ IK_LLVM_IR }; - + /// \brief An input file for the front end. class FrontendInputFile { /// \brief The file name, or "-" to read from standard input. @@ -109,6 +109,13 @@ bool isEmpty() const { return File.empty() && Buffer == nullptr; } bool isFile() const { return !isBuffer(); } bool isBuffer() const { return Buffer != nullptr; } + bool isPreprocessed() const { +return Kind == IK_PreprocessedC || + Kind == IK_PreprocessedCXX || + Kind == IK_PreprocessedObjC || + Kind == IK_PreprocessedObjCXX || + Kind == IK_PreprocessedCuda; + } StringRef getFile() const { assert(isFile()); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30663: Use filename in linemarker when compiling preprocessed source (Revised)
twoh added inline comments. Comment at: test/Frontend/preprocessed-input.c:3 +// RUN: %clang -emit-llvm -S -o - %t.i | FileCheck %s +// CHECK: source_filename = {{.*}}preprocessed-input.c"{{$}} inglorion wrote: > Actually, I think you don't even have to run the preprocessor - you can just > put the file with the linemarker here and check that the name from the > linemarker is propagated, right? > > Also, it seems that there is a similar issue to the one you're trying to fix > when going from .ll to .o (or .ll to .s, for that matter) - the name is taken > from the file you're reading from, not from the source_filename directive in > that file. Of course, that doesn't differ from gcc (given that gcc doesn't > handle .ll files), but you may want to address that, too, for consistency. @inglorion Thanks for the comments! Putting preprocessed file makes sense to me. I recognize the second issue. If I do something like ``` clang -E -o test.i /abspath/test.c clang -g -c -o test.o test.i ``` DW_AT_name is still test.i (for gcc, it is taken from the linemarker as well). Moreover, if we use the absolute path of test.i for clang, i.e. ``` clang -g -c -o test.o /abspath/test.i ``` DW_AT_name becomes /abspath/test.i where DW_AT_comp_dir is /abspath. I think this could be a problem if the user of the object file assumes that DW_AT_name is a relative to DW_AT_comp_dir. I'm planning to address this with a separate patch. https://reviews.llvm.org/D30663 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30663: Use filename in linemarker when compiling preprocessed source (Revised)
twoh updated this revision to Diff 90735. twoh added a comment. Herald added a subscriber: mehdi_amini. addressing comments from @inglorion https://reviews.llvm.org/D30663 Files: include/clang/Frontend/FrontendOptions.h lib/Frontend/FrontendAction.cpp test/Frontend/preprocessed-input.i Index: test/Frontend/preprocessed-input.i === --- /dev/null +++ test/Frontend/preprocessed-input.i @@ -0,0 +1,10 @@ +# 1 "preprocessed-input.c" +# 1 "" 1 +# 1 "" 3 +# 318 "" 3 +# 1 "" 1 +# 1 "" 2 +# 1 "preprocessed-input.c" 2 + +// RUN: %clang -emit-llvm -S -o - %s | FileCheck %s +// CHECK: source_filename = "preprocessed-input.c"{{$}} Index: lib/Frontend/FrontendAction.cpp === --- lib/Frontend/FrontendAction.cpp +++ lib/Frontend/FrontendAction.cpp @@ -19,6 +19,7 @@ #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Parse/ParseAST.h" @@ -187,6 +188,42 @@ return llvm::make_unique(std::move(Consumers)); } +// For preprocessed files, if the first line is the linemarker and specifies +// the original source file name, use that name as the input file name. +static bool ReadOriginalFileName(CompilerInstance &CI, std::string &InputFile) +{ + bool Invalid = false; + auto &SourceMgr = CI.getSourceManager(); + auto MainFileID = SourceMgr.getMainFileID(); + const auto *MainFileBuf = SourceMgr.getBuffer(MainFileID, &Invalid); + if (Invalid) +return false; + + std::unique_ptr RawLexer( + new Lexer(MainFileID, MainFileBuf, SourceMgr, CI.getLangOpts())); + + // If the first line has the syntax of + // + // # NUM "FILENAME" + // + // we use FILENAME as the input file name. + Token T; + if (RawLexer->LexFromRawLexer(T) || T.getKind() != tok::hash) +return false; + if (RawLexer->LexFromRawLexer(T) || T.isAtStartOfLine() || + T.getKind() != tok::numeric_constant) +return false; + RawLexer->LexFromRawLexer(T); + if (T.isAtStartOfLine() || T.getKind() != tok::string_literal) +return false; + + StringLiteralParser Literal(T, CI.getPreprocessor()); + if (Literal.hadError) +return false; + InputFile = Literal.GetString().str(); + return true; +} + bool FrontendAction::BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input) { assert(!Instance && "Already processing a source file!"); @@ -338,6 +375,13 @@ if (!isModelParsingAction()) CI.createASTContext(); +// For preprocessed files, check if the first line specifies the original +// source file name with a linemarker. +std::string OrigFile; +if (Input.isPreprocessed()) + if (ReadOriginalFileName(CI, OrigFile)) +InputFile = OrigFile; + std::unique_ptr Consumer = CreateWrappedASTConsumer(CI, InputFile); if (!Consumer) @@ -430,9 +474,9 @@ // If there is a layout overrides file, attach an external AST source that // provides the layouts from that file. - if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && + if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { -IntrusiveRefCntPtr +IntrusiveRefCntPtr Override(new LayoutOverrideSource( CI.getFrontendOpts().OverrideRecordLayoutsFile)); CI.getASTContext().setExternalSource(Override); Index: include/clang/Frontend/FrontendOptions.h === --- include/clang/Frontend/FrontendOptions.h +++ include/clang/Frontend/FrontendOptions.h @@ -81,7 +81,7 @@ IK_LLVM_IR }; - + /// \brief An input file for the front end. class FrontendInputFile { /// \brief The file name, or "-" to read from standard input. @@ -109,6 +109,13 @@ bool isEmpty() const { return File.empty() && Buffer == nullptr; } bool isFile() const { return !isBuffer(); } bool isBuffer() const { return Buffer != nullptr; } + bool isPreprocessed() const { +return Kind == IK_PreprocessedC || + Kind == IK_PreprocessedCXX || + Kind == IK_PreprocessedObjC || + Kind == IK_PreprocessedObjCXX || + Kind == IK_PreprocessedCuda; + } StringRef getFile() const { assert(isFile()); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D30663: Use filename in linemarker when compiling preprocessed source (Revised)
This revision was automatically updated to reflect the committed changes. Closed by commit rL297194: Use filename in linemarker when compiling preprocessed source (Revised) (authored by twoh). Changed prior to commit: https://reviews.llvm.org/D30663?vs=90735&id=90912#toc Repository: rL LLVM https://reviews.llvm.org/D30663 Files: cfe/trunk/include/clang/Frontend/FrontendOptions.h cfe/trunk/lib/Frontend/FrontendAction.cpp cfe/trunk/test/Frontend/preprocessed-input.i Index: cfe/trunk/include/clang/Frontend/FrontendOptions.h === --- cfe/trunk/include/clang/Frontend/FrontendOptions.h +++ cfe/trunk/include/clang/Frontend/FrontendOptions.h @@ -81,7 +81,7 @@ IK_LLVM_IR }; - + /// \brief An input file for the front end. class FrontendInputFile { /// \brief The file name, or "-" to read from standard input. @@ -109,6 +109,13 @@ bool isEmpty() const { return File.empty() && Buffer == nullptr; } bool isFile() const { return !isBuffer(); } bool isBuffer() const { return Buffer != nullptr; } + bool isPreprocessed() const { +return Kind == IK_PreprocessedC || + Kind == IK_PreprocessedCXX || + Kind == IK_PreprocessedObjC || + Kind == IK_PreprocessedObjCXX || + Kind == IK_PreprocessedCuda; + } StringRef getFile() const { assert(isFile()); Index: cfe/trunk/test/Frontend/preprocessed-input.i === --- cfe/trunk/test/Frontend/preprocessed-input.i +++ cfe/trunk/test/Frontend/preprocessed-input.i @@ -0,0 +1,10 @@ +# 1 "preprocessed-input.c" +# 1 "" 1 +# 1 "" 3 +# 318 "" 3 +# 1 "" 1 +# 1 "" 2 +# 1 "preprocessed-input.c" 2 + +// RUN: %clang -emit-llvm -S -o - %s | FileCheck %s +// CHECK: source_filename = "preprocessed-input.c"{{$}} Index: cfe/trunk/lib/Frontend/FrontendAction.cpp === --- cfe/trunk/lib/Frontend/FrontendAction.cpp +++ cfe/trunk/lib/Frontend/FrontendAction.cpp @@ -19,6 +19,7 @@ #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Parse/ParseAST.h" @@ -187,6 +188,42 @@ return llvm::make_unique(std::move(Consumers)); } +// For preprocessed files, if the first line is the linemarker and specifies +// the original source file name, use that name as the input file name. +static bool ReadOriginalFileName(CompilerInstance &CI, std::string &InputFile) +{ + bool Invalid = false; + auto &SourceMgr = CI.getSourceManager(); + auto MainFileID = SourceMgr.getMainFileID(); + const auto *MainFileBuf = SourceMgr.getBuffer(MainFileID, &Invalid); + if (Invalid) +return false; + + std::unique_ptr RawLexer( + new Lexer(MainFileID, MainFileBuf, SourceMgr, CI.getLangOpts())); + + // If the first line has the syntax of + // + // # NUM "FILENAME" + // + // we use FILENAME as the input file name. + Token T; + if (RawLexer->LexFromRawLexer(T) || T.getKind() != tok::hash) +return false; + if (RawLexer->LexFromRawLexer(T) || T.isAtStartOfLine() || + T.getKind() != tok::numeric_constant) +return false; + RawLexer->LexFromRawLexer(T); + if (T.isAtStartOfLine() || T.getKind() != tok::string_literal) +return false; + + StringLiteralParser Literal(T, CI.getPreprocessor()); + if (Literal.hadError) +return false; + InputFile = Literal.GetString().str(); + return true; +} + bool FrontendAction::BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input) { assert(!Instance && "Already processing a source file!"); @@ -338,6 +375,13 @@ if (!isModelParsingAction()) CI.createASTContext(); +// For preprocessed files, check if the first line specifies the original +// source file name with a linemarker. +std::string OrigFile; +if (Input.isPreprocessed()) + if (ReadOriginalFileName(CI, OrigFile)) +InputFile = OrigFile; + std::unique_ptr Consumer = CreateWrappedASTConsumer(CI, InputFile); if (!Consumer) @@ -430,9 +474,9 @@ // If there is a layout overrides file, attach an external AST source that // provides the layouts from that file. - if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && + if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { -IntrusiveRefCntPtr +IntrusiveRefCntPtr Override(new LayoutOverrideSource( CI.getFrontendOpts().OverrideRecordLayoutsFile)); CI.getASTContext().setExternalSource(Override); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits