[clang] [llvm] [clang] Support per-function [[clang::code_align(N)]] attribute. (PR #80765)

2024-02-11 Thread Anton Bikineev via cfe-commits

AntonBikineev wrote:

> I am not sure a case where people care for specific functions and want 
> annotating them.

Our (V8 and Chromium) use case is that we know some hot functions that suffer 
from misaligned jumps. These functions would ideally be annotated with the 
attribute. We don't want to use the option for the entire binary as it'd 
significantly increase the binary size.

The alternative would be moving those functions into a separate TU(s), but it's 
just cumbersome.

https://github.com/llvm/llvm-project/pull/80765
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [clang] Support per-function [[clang::code_align(N)]] attribute. (PR #80765)

2024-02-09 Thread Anton Bikineev via cfe-commits

AntonBikineev wrote:

> Aligning the targets of branches is a different thing from what you've 
> implemented. There are basic blocks which are not branch targets, and there 
> are branch targets which are not at the beginning of a basic block. (Branch 
> targets that aren't at the beginning of a basic block are rare on most 
> targets, but it doesn't seem like something we should completely ignore.)

That makes sense, thanks. Would there be an interest in something like 
[[clang::x86_align_branch_boundary]] that would align branch instructions per 
function?

https://github.com/llvm/llvm-project/pull/80765
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang] Support per-function [[clang::code_align(N)]] attribute. (PR #80765)

2024-02-05 Thread Anton Bikineev via cfe-commits

https://github.com/AntonBikineev updated 
https://github.com/llvm/llvm-project/pull/80765

>From 88151098d3087f95d3a5b652309a12fb2e9f757e Mon Sep 17 00:00:00 2001
From: Anton Bikineev 
Date: Mon, 5 Feb 2024 12:24:17 +0100
Subject: [PATCH] [clang] Support per-function [[clang::code_align(N)]]
 attribute.

The existing attribute works only for loop headers. This can
unfortunately be quite limiting, especially as a protection against the
"Jump Conditional Code Erratum" [0] (for example, if there is an
unaligned check in a hot loop). The command line option
-malign-branch-boundary can help with that, but it's too coarse-grained
and can significantly increase the binary size.

This change introduces a per-function [[clang::code_align(N)]] attribute
that aligns all the basic blocks of a function by the given N.

[0] 
https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf
---
 clang/include/clang/Basic/Attr.td |  7 ++--
 clang/include/clang/Basic/AttrDocs.td | 16 ---
 clang/lib/CodeGen/CodeGenModule.cpp   |  6 +++
 clang/lib/Sema/SemaDeclAttr.cpp   | 10 +
 clang/test/CodeGen/code_align_function.c  | 42 +++
 ...a-attribute-supported-attributes-list.test |  1 +
 clang/test/Sema/code_align.c  | 14 ++-
 llvm/lib/CodeGen/MachineBlockPlacement.cpp| 28 ++---
 .../CodeGen/X86/code-align-basic-blocks.ll| 29 +
 9 files changed, 137 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/CodeGen/code_align_function.c
 create mode 100644 llvm/test/CodeGen/X86/code-align-basic-blocks.ll

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index b2d5309e142c1..abce685e9f7a6 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4435,10 +4435,11 @@ def PreferredType: InheritableAttr {
   let Documentation = [PreferredTypeDocumentation];
 }
 
-def CodeAlign: StmtAttr {
+def CodeAlign : InheritableAttr {
   let Spellings = [Clang<"code_align">];
-  let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
-  ErrorDiag, "'for', 'while', and 'do' 
statements">;
+  let Subjects =
+  SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt, Function],
+  ErrorDiag, "'for', 'while', 'do' statements and functions">;
   let Args = [ExprArgument<"Alignment">];
   let Documentation = [CodeAlignAttrDocs];
   let AdditionalMembers = [{
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 041786f37fb8a..57b63469f1573 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7704,11 +7704,12 @@ def CodeAlignAttrDocs : Documentation {
   let Category = DocCatVariable;
   let Heading = "clang::code_align";
   let Content = [{
-The ``clang::code_align(N)`` attribute applies to a loop and specifies the byte
-alignment for a loop. The attribute accepts a positive integer constant
-initialization expression indicating the number of bytes for the minimum
-alignment boundary. Its value must be a power of 2, between 1 and 4096
-(inclusive).
+The ``clang::code_align(N)`` attribute applies to a loop or a function. When
+applied to a loop it specifies the byte alignment for the loop header. When
+applied to a function it aligns all the basic blocks of the function. The
+attribute accepts a positive integer constant initialization expression
+indicating the number of bytes for the minimum alignment boundary. Its value
+must be a power of 2, between 1 and 4096 (inclusive).
 
 .. code-block:: c++
 
@@ -7738,6 +7739,11 @@ alignment boundary. Its value must be a power of 2, 
between 1 and 4096
 [[clang::code_align(A)]] for(;;) { }
   }
 
+  [[clang:code_align(16)]] int foo(bool b) {
+if (b) return 2;
+return 3;
+  }
+
   }];
 }
 
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 36b63d78b06f8..87a822e91fff6 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2515,6 +2515,12 @@ void 
CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
   F->setAlignment(std::max(llvm::Align(2), F->getAlign().valueOrOne()));
   }
 
+  if (const auto *CodeAlign = D->getAttr()) {
+const auto *CE = cast(CodeAlign->getAlignment());
+std::string ArgValStr = llvm::toString(CE->getResultAsAPSInt(), 10);
+F->addFnAttr("align-basic-blocks", ArgValStr);
+  }
+
   // In the cross-dso CFI mode with canonical jump tables, we want !type
   // attributes on definitions only.
   if (CodeGenOpts.SanitizeCfiCrossDso &&
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index d785714c4d811..40412801b632a 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -9036,6 +9036,12 @@ static void handleArmNewAttr(Sema , 

[llvm] [clang] [clang] Support per-function [[clang::code_align(N)]] attribute. (PR #80765)

2024-02-05 Thread Anton Bikineev via cfe-commits

https://github.com/AntonBikineev updated 
https://github.com/llvm/llvm-project/pull/80765

>From 99d2cc55fb952361b1fe04e2c21dcb5b04f11d47 Mon Sep 17 00:00:00 2001
From: Anton Bikineev 
Date: Mon, 5 Feb 2024 12:24:17 +0100
Subject: [PATCH] [clang] Support per-function [[clang::code_align(N)]]
 attribute.

The existing attribute works only for loop headers. This can
unfortunately be quite limiting, especially as a protection against the
"Jump Conditional Code Erratum" [0] (for example, if there is an
unaligned check in a hot loop). The command line option
-malign-branch-boundary can help with that, but it's too coarse-grained
and can significantly increase the binary size.

This change introduces a per-function [[clang::code_align(N)]] attribute
that aligns all the basic blocks of a function by the given N.

[0] 
https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf
---
 clang/include/clang/Basic/Attr.td |  7 ++--
 clang/include/clang/Basic/AttrDocs.td | 16 ---
 clang/lib/CodeGen/CodeGenModule.cpp   |  6 +++
 clang/lib/Sema/SemaDeclAttr.cpp   | 10 +
 clang/test/CodeGen/code_align_function.c  | 42 +++
 clang/test/Sema/code_align.c  | 14 ++-
 llvm/lib/CodeGen/MachineBlockPlacement.cpp| 28 ++---
 .../CodeGen/X86/code-align-basic-blocks.ll| 29 +
 8 files changed, 136 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/CodeGen/code_align_function.c
 create mode 100644 llvm/test/CodeGen/X86/code-align-basic-blocks.ll

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index b2d5309e142c1a..abce685e9f7a64 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4435,10 +4435,11 @@ def PreferredType: InheritableAttr {
   let Documentation = [PreferredTypeDocumentation];
 }
 
-def CodeAlign: StmtAttr {
+def CodeAlign : InheritableAttr {
   let Spellings = [Clang<"code_align">];
-  let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
-  ErrorDiag, "'for', 'while', and 'do' 
statements">;
+  let Subjects =
+  SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt, Function],
+  ErrorDiag, "'for', 'while', 'do' statements and functions">;
   let Args = [ExprArgument<"Alignment">];
   let Documentation = [CodeAlignAttrDocs];
   let AdditionalMembers = [{
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 041786f37fb8a7..57b63469f1573f 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7704,11 +7704,12 @@ def CodeAlignAttrDocs : Documentation {
   let Category = DocCatVariable;
   let Heading = "clang::code_align";
   let Content = [{
-The ``clang::code_align(N)`` attribute applies to a loop and specifies the byte
-alignment for a loop. The attribute accepts a positive integer constant
-initialization expression indicating the number of bytes for the minimum
-alignment boundary. Its value must be a power of 2, between 1 and 4096
-(inclusive).
+The ``clang::code_align(N)`` attribute applies to a loop or a function. When
+applied to a loop it specifies the byte alignment for the loop header. When
+applied to a function it aligns all the basic blocks of the function. The
+attribute accepts a positive integer constant initialization expression
+indicating the number of bytes for the minimum alignment boundary. Its value
+must be a power of 2, between 1 and 4096 (inclusive).
 
 .. code-block:: c++
 
@@ -7738,6 +7739,11 @@ alignment boundary. Its value must be a power of 2, 
between 1 and 4096
 [[clang::code_align(A)]] for(;;) { }
   }
 
+  [[clang:code_align(16)]] int foo(bool b) {
+if (b) return 2;
+return 3;
+  }
+
   }];
 }
 
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 36b63d78b06f83..87a822e91fff61 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2515,6 +2515,12 @@ void 
CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
   F->setAlignment(std::max(llvm::Align(2), F->getAlign().valueOrOne()));
   }
 
+  if (const auto *CodeAlign = D->getAttr()) {
+const auto *CE = cast(CodeAlign->getAlignment());
+std::string ArgValStr = llvm::toString(CE->getResultAsAPSInt(), 10);
+F->addFnAttr("align-basic-blocks", ArgValStr);
+  }
+
   // In the cross-dso CFI mode with canonical jump tables, we want !type
   // attributes on definitions only.
   if (CodeGenOpts.SanitizeCfiCrossDso &&
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index d785714c4d811e..40412801b632ae 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -9036,6 +9036,12 @@ static void handleArmNewAttr(Sema , Decl *D, const 
ParsedAttr ) {
 

[llvm] [clang] [clang] Support per-function [[clang::code_align(N)]] attribute. (PR #80765)

2024-02-05 Thread Anton Bikineev via cfe-commits

https://github.com/AntonBikineev created 
https://github.com/llvm/llvm-project/pull/80765

The existing attribute works only for loop headers. This can unfortunately be 
quite limiting, especially as a protection against the "Jump Conditional Code 
Erratum" [0] (for example, if there is an unaligned check in a hot loop). The 
command line option -malign-branch-boundary can help with that, but it's too 
coarse-grained and can significantly increase the binary size.

This change introduces a per-function [[clang::code_align(N)]] attribute that 
aligns all the basic blocks of a function by the given N.

[0] 
https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf

>From ff8cf4e87473dec2e3f55114cb92ae5a63d9488c Mon Sep 17 00:00:00 2001
From: Anton Bikineev 
Date: Mon, 5 Feb 2024 12:24:17 +0100
Subject: [PATCH] [clang] Support per-function [[clang::code_align(N)]]
 attribute.

The existing attribute works only for loop headers. This can
unfortunately be quite limiting, especially as a protection against the
"Jump Conditional Code Erratum" [0] (for example, if there is an
unaligned check in a hot loop). The command line option
-malign-branch-boundary can help with that, but it's too coarse-grained
and can significantly increase the binary size.

This change introduces a per-function [[clang::code_align(N)]] attribute
that aligns all the basic blocks of a function by the given N.

[0] 
https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf
---
 clang/include/clang/Basic/Attr.td |  7 ++--
 clang/include/clang/Basic/AttrDocs.td | 16 ---
 clang/lib/CodeGen/CodeGenModule.cpp   |  6 +++
 clang/lib/Sema/SemaDeclAttr.cpp   | 10 +
 clang/test/CodeGen/code_align_function.c  | 42 +++
 clang/test/Sema/code_align.c  | 14 ++-
 llvm/lib/CodeGen/MachineBlockPlacement.cpp| 27 +---
 .../CodeGen/X86/code-align-basic-blocks.ll| 29 +
 8 files changed, 135 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/CodeGen/code_align_function.c
 create mode 100644 llvm/test/CodeGen/X86/code-align-basic-blocks.ll

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index b2d5309e142c1..abce685e9f7a6 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4435,10 +4435,11 @@ def PreferredType: InheritableAttr {
   let Documentation = [PreferredTypeDocumentation];
 }
 
-def CodeAlign: StmtAttr {
+def CodeAlign : InheritableAttr {
   let Spellings = [Clang<"code_align">];
-  let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
-  ErrorDiag, "'for', 'while', and 'do' 
statements">;
+  let Subjects =
+  SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt, Function],
+  ErrorDiag, "'for', 'while', 'do' statements and functions">;
   let Args = [ExprArgument<"Alignment">];
   let Documentation = [CodeAlignAttrDocs];
   let AdditionalMembers = [{
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 041786f37fb8a..57b63469f1573 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7704,11 +7704,12 @@ def CodeAlignAttrDocs : Documentation {
   let Category = DocCatVariable;
   let Heading = "clang::code_align";
   let Content = [{
-The ``clang::code_align(N)`` attribute applies to a loop and specifies the byte
-alignment for a loop. The attribute accepts a positive integer constant
-initialization expression indicating the number of bytes for the minimum
-alignment boundary. Its value must be a power of 2, between 1 and 4096
-(inclusive).
+The ``clang::code_align(N)`` attribute applies to a loop or a function. When
+applied to a loop it specifies the byte alignment for the loop header. When
+applied to a function it aligns all the basic blocks of the function. The
+attribute accepts a positive integer constant initialization expression
+indicating the number of bytes for the minimum alignment boundary. Its value
+must be a power of 2, between 1 and 4096 (inclusive).
 
 .. code-block:: c++
 
@@ -7738,6 +7739,11 @@ alignment boundary. Its value must be a power of 2, 
between 1 and 4096
 [[clang::code_align(A)]] for(;;) { }
   }
 
+  [[clang:code_align(16)]] int foo(bool b) {
+if (b) return 2;
+return 3;
+  }
+
   }];
 }
 
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 36b63d78b06f8..87a822e91fff6 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2515,6 +2515,12 @@ void 
CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
   F->setAlignment(std::max(llvm::Align(2), F->getAlign().valueOrOne()));
   }
 
+  if (const auto *CodeAlign = D->getAttr()) {
+const auto 

[clang] 7b85e76 - [PGO] Consider parent context when weighing branches with likelyhood.

2022-10-08 Thread Anton Bikineev via cfe-commits

Author: Anton Bikineev
Date: 2022-10-08T23:49:27+02:00
New Revision: 7b85e765000df36fcc6a5191dec9a28f444245ba

URL: 
https://github.com/llvm/llvm-project/commit/7b85e765000df36fcc6a5191dec9a28f444245ba
DIFF: 
https://github.com/llvm/llvm-project/commit/7b85e765000df36fcc6a5191dec9a28f444245ba.diff

LOG: [PGO] Consider parent context when weighing branches with likelyhood.

Generally, with PGO enabled the C++20 likelyhood attributes shall be
dropped assuming the profile has a good coverage. However, currently
this is not the case for the following code:

 if (always_false()) [[likely]] {
   ...
 }

The patch fixes this and drops the attribute, if the parent context was
executed in the profile. The patch still preserves the attribute, if the
parent context was not executed, e.g. to support the cases when the
profile has insufficient coverage.

Differential Revision: https://reviews.llvm.org/D134456

Added: 
clang/test/Profile/Inputs/cxx-never-executed-branch.proftext
clang/test/Profile/cxx-never-executed-branch.cpp

Modified: 
clang/lib/CodeGen/CGStmt.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 9935fcc0d3ea2..ebbc79cc8b4b6 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -815,11 +815,20 @@ void CodeGenFunction::EmitIfStmt(const IfStmt ) {
   // Prefer the PGO based weights over the likelihood attribute.
   // When the build isn't optimized the metadata isn't used, so don't generate
   // it.
+  // Also, 
diff erentiate between disabled PGO and a never executed branch with
+  // PGO. Assuming PGO is in use:
+  // - we want to ignore the [[likely]] attribute if the branch is never
+  // executed,
+  // - assuming the profile is poor, preserving the attribute may still be
+  // beneficial.
+  // As an approximation, preserve the attribute only if both the branch and 
the
+  // parent context were not executed.
   Stmt::Likelihood LH = Stmt::LH_None;
-  uint64_t Count = getProfileCount(S.getThen());
-  if (!Count && CGM.getCodeGenOpts().OptimizationLevel)
+  uint64_t ThenCount = getProfileCount(S.getThen());
+  if (!ThenCount && !getCurrentProfileCount() &&
+  CGM.getCodeGenOpts().OptimizationLevel)
 LH = Stmt::getLikelihood(S.getThen(), S.getElse());
-  EmitBranchOnBoolExpr(S.getCond(), ThenBlock, ElseBlock, Count, LH);
+  EmitBranchOnBoolExpr(S.getCond(), ThenBlock, ElseBlock, ThenCount, LH);
 
   // Emit the 'then' code.
   EmitBlock(ThenBlock);

diff  --git a/clang/test/Profile/Inputs/cxx-never-executed-branch.proftext 
b/clang/test/Profile/Inputs/cxx-never-executed-branch.proftext
new file mode 100644
index 0..64a55b3e52b37
--- /dev/null
+++ b/clang/test/Profile/Inputs/cxx-never-executed-branch.proftext
@@ -0,0 +1,13 @@
+_Z13is_in_profilev
+0x00029f493458
+2
+2
+# The branch is never executed.
+0
+
+_Z17is_not_in_profilev
+0x00029f493458
+2
+# The function was never executed
+0
+0

diff  --git a/clang/test/Profile/cxx-never-executed-branch.cpp 
b/clang/test/Profile/cxx-never-executed-branch.cpp
new file mode 100644
index 0..812f65f3996d3
--- /dev/null
+++ b/clang/test/Profile/cxx-never-executed-branch.cpp
@@ -0,0 +1,32 @@
+// Test that clang doesn't emit llvm.expect when the counter is 0
+
+// RUN: llvm-profdata merge %S/Inputs/cxx-never-executed-branch.proftext -o 
%t.profdata
+// RUN: %clang_cc1 -std=c++20 %s -triple %itanium_abi_triple -O2 -o - 
-emit-llvm -fprofile-instrument-use-path=%t.profdata -disable-llvm-passes | 
FileCheck %s
+
+int rand();
+
+// CHECK: define {{.*}}@_Z13is_in_profilev
+// CHECK-NOT: call {{.*}}@llvm.expect
+
+int is_in_profile() {
+  int rando = rand();
+  int x = 0;
+  if (rando == 0) [[likely]]
+x = 2;
+  else
+x = 3;
+  return x;
+}
+
+// CHECK: define {{.*}}@_Z17is_not_in_profilev
+// CHECK: call {{.*}}@llvm.expect
+
+int is_not_in_profile() {
+  int rando = rand();
+  int x = 0;
+  if (rando == 0) [[likely]]
+x = 2;
+  else
+x = 3;
+  return x;
+}



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 6954515 - [Sema] Move 'char-expression-as-unsigned < 0' into a separate diagnostic

2021-04-13 Thread Anton Bikineev via cfe-commits

Author: Anton Bikineev
Date: 2021-04-14T01:01:40+02:00
New Revision: 69545154cc28a0a7f813174253c6cb428666eb3a

URL: 
https://github.com/llvm/llvm-project/commit/69545154cc28a0a7f813174253c6cb428666eb3a
DIFF: 
https://github.com/llvm/llvm-project/commit/69545154cc28a0a7f813174253c6cb428666eb3a.diff

LOG: [Sema] Move 'char-expression-as-unsigned < 0' into a separate diagnostic

This change splits '-Wtautological-unsigned-zero-compare' by reporting
char-expressions-interpreted-as-unsigned under a separate diagnostic
'-Wtautological-unsigned-char-zero-compare'. This is beneficial for
projects that want to enable '-Wtautological-unsigned-zero-compare' but at
the same time want to keep code portable for platforms with char being
signed or unsigned, such as Chromium.

Differential Revision: https://reviews.llvm.org/D99808

Added: 
clang/test/Sema/tautological-unsigned-char-zero-compare.cc

Modified: 
clang/include/clang/Basic/DiagnosticGroups.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaChecking.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 85f798013a3d..e202645d1f2b 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -591,11 +591,13 @@ def SwiftNameAttribute : 
DiagGroup<"swift-name-attribute">;
 def IntInBoolContext : DiagGroup<"int-in-bool-context">;
 def TautologicalTypeLimitCompare : 
DiagGroup<"tautological-type-limit-compare">;
 def TautologicalUnsignedZeroCompare : 
DiagGroup<"tautological-unsigned-zero-compare">;
+def TautologicalUnsignedCharZeroCompare : 
DiagGroup<"tautological-unsigned-char-zero-compare">;
 def TautologicalUnsignedEnumZeroCompare : 
DiagGroup<"tautological-unsigned-enum-zero-compare">;
 // For compatibility with GCC. Tautological comparison warnings for constants
 // that are an extremal value of the type.
 def TypeLimits : DiagGroup<"type-limits", [TautologicalTypeLimitCompare,
TautologicalUnsignedZeroCompare,
+   TautologicalUnsignedCharZeroCompare,

TautologicalUnsignedEnumZeroCompare]>;
 // Additional tautological comparison warnings based on the expression, not
 // only on its type.

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index af7eea06f6f5..afef86ab5890 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6784,6 +6784,10 @@ def warn_unsigned_always_true_comparison : Warning<
   "result of comparison of %select{%3|unsigned expression}0 %2 "
   "%select{unsigned expression|%3}0 is always %4">,
   InGroup, DefaultIgnore;
+def warn_unsigned_char_always_true_comparison : Warning<
+  "result of comparison of %select{%3|char expression}0 %2 "
+  "%select{char expression|%3}0 is always %4, since char is interpreted as "
+  "unsigned">, InGroup, DefaultIgnore;
 def warn_unsigned_enum_always_true_comparison : Warning<
   "result of comparison of %select{%3|unsigned enum expression}0 %2 "
   "%select{unsigned enum expression|%3}0 is always %4">,

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index fa5e184d2864..7b6e0541aa4d 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -11446,11 +11446,14 @@ static bool CheckTautologicalComparison(Sema , 
BinaryOperator *E,
 << OtherIsBooleanDespiteType << *Result
 << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
   } else {
-unsigned Diag = (isKnownToHaveUnsignedValue(OriginalOther) && Value == 0)
-? (HasEnumType(OriginalOther)
-   ? 
diag::warn_unsigned_enum_always_true_comparison
-   : diag::warn_unsigned_always_true_comparison)
-: diag::warn_tautological_constant_compare;
+bool IsCharTy = OtherT.withoutLocalFastQualifiers() == S.Context.CharTy;
+unsigned Diag =
+(isKnownToHaveUnsignedValue(OriginalOther) && Value == 0)
+? (HasEnumType(OriginalOther)
+   ? diag::warn_unsigned_enum_always_true_comparison
+   : IsCharTy ? diag::warn_unsigned_char_always_true_comparison
+  : diag::warn_unsigned_always_true_comparison)
+: diag::warn_tautological_constant_compare;
 
 S.Diag(E->getOperatorLoc(), Diag)
 << RhsConstant << OtherT << E->getOpcodeStr() << OS.str() << *Result

diff  --git a/clang/test/Sema/tautological-unsigned-char-zero-compare.cc 
b/clang/test/Sema/tautological-unsigned-char-zero-compare.cc
new file mode 100644
index ..4d14954b3213
--- /dev/null
+++ 

[clang] dc7ebd2 - [C++2b] Support size_t literals

2021-03-31 Thread Anton Bikineev via cfe-commits

Author: Anton Bikineev
Date: 2021-03-31T13:36:23Z
New Revision: dc7ebd2cb0cf4a83bb6cd1bfc8853b0a30054777

URL: 
https://github.com/llvm/llvm-project/commit/dc7ebd2cb0cf4a83bb6cd1bfc8853b0a30054777
DIFF: 
https://github.com/llvm/llvm-project/commit/dc7ebd2cb0cf4a83bb6cd1bfc8853b0a30054777.diff

LOG: [C++2b] Support size_t literals

This adds support for C++2b's z/uz suffixes for size_t literals (P0330).

Added: 
clang/test/Lexer/size_t-literal.cpp
clang/test/SemaCXX/size_t-literal.cpp

Modified: 
clang/include/clang/Basic/DiagnosticCommonKinds.td
clang/include/clang/Lex/LiteralSupport.h
clang/lib/Frontend/InitPreprocessor.cpp
clang/lib/Lex/LiteralSupport.cpp
clang/lib/Lex/PPExpressions.cpp
clang/lib/Sema/SemaExpr.cpp
clang/test/Lexer/cxx-features.cpp
clang/test/SemaCXX/cxx1y-user-defined-literals.cpp
clang/www/cxx_status.html

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td 
b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index a237d492de201..eab8206b104dc 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -187,6 +187,17 @@ def ext_cxx11_longlong : Extension<
 def warn_cxx98_compat_longlong : Warning<
   "'long long' is incompatible with C++98">,
   InGroup, DefaultIgnore;
+def ext_cxx2b_size_t_suffix : ExtWarn<
+  "'size_t' suffix for literals is a C++2b extension">,
+  InGroup;
+def warn_cxx20_compat_size_t_suffix : Warning<
+  "'size_t' suffix for literals is incompatible with C++ standards before "
+  "C++2b">, InGroup, DefaultIgnore;
+def err_cxx2b_size_t_suffix: Error<
+  "'size_t' suffix for literals is a C++2b feature">;
+def err_size_t_literal_too_large: Error<
+  "%select{signed |}0'size_t' literal is out of range of possible "
+  "%select{signed |}0'size_t' values">;
 def err_integer_literal_too_large : Error<
   "integer literal is too large to be represented in any %select{signed |}0"
   "integer type">;

diff  --git a/clang/include/clang/Lex/LiteralSupport.h 
b/clang/include/clang/Lex/LiteralSupport.h
index 0c4f0fe277b7c..f131f045a73ea 100644
--- a/clang/include/clang/Lex/LiteralSupport.h
+++ b/clang/include/clang/Lex/LiteralSupport.h
@@ -63,6 +63,7 @@ class NumericLiteralParser {
   bool isUnsigned : 1;
   bool isLong : 1;  // This is *not* set for long long.
   bool isLongLong : 1;
+  bool isSizeT : 1; // 1z, 1uz (C++2b)
   bool isHalf : 1;  // 1.0h
   bool isFloat : 1; // 1.0f
   bool isImaginary : 1; // 1.0i

diff  --git a/clang/lib/Frontend/InitPreprocessor.cpp 
b/clang/lib/Frontend/InitPreprocessor.cpp
index 15f254515822b..3d69c59d166d0 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -589,6 +589,9 @@ static void InitializeCPlusPlusFeatureTestMacros(const 
LangOptions ,
 //Builder.defineMacro("__cpp_modules", "201907L");
 //Builder.defineMacro("__cpp_using_enum", "201907L");
   }
+  // C++2b features.
+  if (LangOpts.CPlusPlus2b)
+Builder.defineMacro("__cpp_size_t_suffix", "202011L");
   if (LangOpts.Char8)
 Builder.defineMacro("__cpp_char8_t", "201811L");
   Builder.defineMacro("__cpp_impl_destroying_delete", "201806L");

diff  --git a/clang/lib/Lex/LiteralSupport.cpp 
b/clang/lib/Lex/LiteralSupport.cpp
index df98516ee61d1..bfcb3c478b62d 100644
--- a/clang/lib/Lex/LiteralSupport.cpp
+++ b/clang/lib/Lex/LiteralSupport.cpp
@@ -546,6 +546,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef 
TokSpelling,
   isLong = false;
   isUnsigned = false;
   isLongLong = false;
+  isSizeT = false;
   isHalf = false;
   isFloat = false;
   isImaginary = false;
@@ -589,6 +590,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef 
TokSpelling,
   // integer constant.
   bool isFixedPointConstant = isFixedPointLiteral();
   bool isFPConstant = isFloatingLiteral();
+  bool HasSize = false;
 
   // Loop over all of the characters of the suffix.  If we see something bad,
   // we break out of the loop.
@@ -616,14 +618,17 @@ NumericLiteralParser::NumericLiteralParser(StringRef 
TokSpelling,
   if (!(LangOpts.Half || LangOpts.FixedPoint))
 break;
   if (isIntegerLiteral()) break;  // Error for integer constant.
-  if (isHalf || isFloat || isLong) break; // HH, FH, LH invalid.
+  if (HasSize)
+break;
+  HasSize = true;
   isHalf = true;
   continue;  // Success.
 case 'f':  // FP Suffix for "float"
 case 'F':
   if (!isFPConstant) break;  // Error for integer constant.
-  if (isHalf || isFloat || isLong || isFloat128)
-break; // HF, FF, LF, QF invalid.
+  if (HasSize)
+break;
+  HasSize = true;
 
   // CUDA host and device may have 
diff erent _Float16 support, therefore
   // allows f16 literals to avoid false alarm.
@@ -640,8 +645,9 @@ 

[clang] 4f8e299 - [Sema] Fix diagnostics for one-byte length modifier

2021-03-09 Thread Anton Bikineev via cfe-commits

Author: Anton Bikineev
Date: 2021-03-09T16:56:20+01:00
New Revision: 4f8e299785e860cf974d696d7ca83b70a94977fe

URL: 
https://github.com/llvm/llvm-project/commit/4f8e299785e860cf974d696d7ca83b70a94977fe
DIFF: 
https://github.com/llvm/llvm-project/commit/4f8e299785e860cf974d696d7ca83b70a94977fe.diff

LOG: [Sema] Fix diagnostics for one-byte length modifier

In case a char-literal of type int (C/ObjectiveC) corresponds to a
format specifier with the %hh length modifier, don't treat the literal
as of type char for issuing diagnostics, as otherwise this results in:

printf("%hhd", 'e');
warning: format specifies type 'char' but the argument has type 'char'.

Differential revision: https://reviews.llvm.org/D97951

Added: 


Modified: 
clang/lib/Sema/SemaChecking.cpp
clang/test/FixIt/format.m

Removed: 




diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index fef6a9306eaf..e390159a8f64 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -8730,8 +8730,11 @@ CheckPrintfHandler::checkFormatExpr(const 
analyze_printf::PrintfSpecifier ,
   } else if (const CharacterLiteral *CL = dyn_cast(E)) {
 // Special case for 'a', which has type 'int' in C.
 // Note, however, that we do /not/ want to treat multibyte constants like
-// 'MooV' as characters! This form is deprecated but still exists.
-if (ExprTy == S.Context.IntTy)
+// 'MooV' as characters! This form is deprecated but still exists. In
+// addition, don't treat expressions as of type 'char' if one byte length
+// modifier is provided.
+if (ExprTy == S.Context.IntTy &&
+FS.getLengthModifier().getKind() != LengthModifier::AsChar)
   if (llvm::isUIntN(S.Context.getCharWidth(), CL->getValue()))
 ExprTy = S.Context.CharTy;
   }

diff  --git a/clang/test/FixIt/format.m b/clang/test/FixIt/format.m
index ef27b1bac353..0d173846d0ad 100644
--- a/clang/test/FixIt/format.m
+++ b/clang/test/FixIt/format.m
@@ -169,6 +169,12 @@ void test_char(char c, signed char s, unsigned char u, 
uint8_t n) {
 
   NSLog(@"%@", 'abcd'); // expected-warning{{format specifies type 'id' but 
the argument has type 'int'}}
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
+
+  NSLog(@"%hhd", 'a'); // expected-warning{{format specifies type 'char' but 
the argument has type 'int'}}
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:15}:"%d"
+
+  NSLog(@"%hhu", 'a'); // expected-warning{{format specifies type 'unsigned 
char' but the argument has type 'int'}}
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:15}:"%d"
 }
 
 void multichar_constants_false_negative() {



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] d36a033 - [clang-tidy] New checker performance-trivially-destructible-check

2019-11-01 Thread Anton Bikineev via cfe-commits

Author: Anton Bikineev
Date: 2019-11-01T16:16:49+01:00
New Revision: d36a0333102698a1398971d0717465322b1c5c2c

URL: 
https://github.com/llvm/llvm-project/commit/d36a0333102698a1398971d0717465322b1c5c2c
DIFF: 
https://github.com/llvm/llvm-project/commit/d36a0333102698a1398971d0717465322b1c5c2c.diff

LOG: [clang-tidy] New checker performance-trivially-destructible-check

Checks for types which can be made trivially-destructible by removing
out-of-line defaulted destructor declarations.

The check is motivated by the work on C++ garbage collector in Blink
(rendering engine for Chrome), which strives to minimize destructors and
improve runtime of sweeping phase.

In the entire chromium codebase the check hits over 2000 times.

Differential Revision: https://reviews.llvm.org/D69435

Added: 
clang-tools-extra/clang-tidy/performance/TriviallyDestructibleCheck.cpp
clang-tools-extra/clang-tidy/performance/TriviallyDestructibleCheck.h

clang-tools-extra/docs/clang-tidy/checks/performance-trivially-destructible.rst

clang-tools-extra/test/clang-tidy/checkers/performance-trivially-destructible.cpp

Modified: 
clang-tools-extra/clang-tidy/performance/CMakeLists.txt
clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
clang-tools-extra/clang-tidy/utils/Matchers.h
clang-tools-extra/clang-tidy/utils/TypeTraits.cpp
clang-tools-extra/clang-tidy/utils/TypeTraits.h
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/list.rst

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index b6302a5ff815..cde2e246bf9e 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -11,6 +11,7 @@ add_clang_library(clangTidyPerformanceModule
   MoveConstructorInitCheck.cpp
   NoexceptMoveConstructorCheck.cpp
   PerformanceTidyModule.cpp
+  TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitialization.cpp
   UnnecessaryValueParamCheck.cpp

diff  --git 
a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index f4b620a14f85..269d09b98a68 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -18,6 +18,7 @@
 #include "MoveConstArgCheck.h"
 #include "MoveConstructorInitCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
+#include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitialization.h"
 #include "UnnecessaryValueParamCheck.h"
@@ -47,6 +48,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-move-constructor-init");
 CheckFactories.registerCheck(
 "performance-noexcept-move-constructor");
+CheckFactories.registerCheck(
+"performance-trivially-destructible");
 CheckFactories.registerCheck(
 "performance-type-promotion-in-math-fn");
 CheckFactories.registerCheck(

diff  --git 
a/clang-tools-extra/clang-tidy/performance/TriviallyDestructibleCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/TriviallyDestructibleCheck.cpp
new file mode 100644
index ..5ed705b0cd79
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/TriviallyDestructibleCheck.cpp
@@ -0,0 +1,82 @@
+//===--- TriviallyDestructibleCheck.cpp - clang-tidy 
--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "TriviallyDestructibleCheck.h"
+#include "../utils/LexerUtils.h"
+#include "../utils/Matchers.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+using namespace clang::ast_matchers::internal;
+using namespace clang::tidy::matchers;
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+namespace {
+
+AST_MATCHER(Decl, isFirstDecl) { return Node.isFirstDecl(); }
+
+AST_MATCHER_P(CXXRecordDecl, hasBase, Matcher, InnerMatcher) {
+  for (const CXXBaseSpecifier  : Node.bases()) {
+QualType BaseType = BaseSpec.getType();
+if (InnerMatcher.matches(BaseType, Finder, Builder))
+  return true;
+  }
+  return false;
+}
+
+} // namespace
+
+void TriviallyDestructibleCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus11)
+return;
+
+  Finder->addMatcher(
+  cxxDestructorDecl(
+  isDefaulted(),
+  unless(anyOf(isFirstDecl(), isVirtual(),
+   

r368152 - [clang] Fix mismatched args constructing AddressSpaceAttr.

2019-08-07 Thread Anton Bikineev via cfe-commits
Author: antonbikineev
Date: Wed Aug  7 04:12:43 2019
New Revision: 368152

URL: http://llvm.org/viewvc/llvm-project?rev=368152=rev
Log:
[clang] Fix mismatched args constructing AddressSpaceAttr.

Differential Revision: https://reviews.llvm.org/D65589

Modified:
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/unittests/AST/ASTTraverserTest.cpp

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=368152=368151=368152=diff
==
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Aug  7 04:12:43 2019
@@ -5978,9 +5978,9 @@ static void HandleAddressSpaceTypeAttrib
 }
 
 ASTContext  = S.Context;
-auto *ASAttr = ::new (Ctx) AddressSpaceAttr(
-Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex(),
-static_cast(ASIdx));
+auto *ASAttr = ::new (Ctx)
+AddressSpaceAttr(Attr.getRange(), Ctx, static_cast(ASIdx),
+ Attr.getAttributeSpellingListIndex());
 
 // If the expression is not value dependent (not templated), then we can
 // apply the address space qualifiers just to the equivalent type.

Modified: cfe/trunk/unittests/AST/ASTTraverserTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTTraverserTest.cpp?rev=368152=368151=368152=diff
==
--- cfe/trunk/unittests/AST/ASTTraverserTest.cpp (original)
+++ cfe/trunk/unittests/AST/ASTTraverserTest.cpp Wed Aug  7 04:12:43 2019
@@ -139,6 +139,8 @@ struct templ
 { 
 };
 
+void parmvardecl_attr(struct A __attribute__((address_space(19)))*);
+
 )cpp");
 
   const FunctionDecl *Func = getFunctionNode(AST.get(), "func");
@@ -220,5 +222,16 @@ FullComment
 R"cpp(
 TemplateArgument
 )cpp");
+
+  Func = getFunctionNode(AST.get(), "parmvardecl_attr");
+
+  const auto *Parm = Func->getParamDecl(0);
+  const auto TL = Parm->getTypeSourceInfo()->getTypeLoc();
+  ASSERT_TRUE(TL.getType()->isPointerType());
+
+  const auto ATL = TL.getNextTypeLoc().getAs();
+  const auto *AS = cast(ATL.getAttr());
+  EXPECT_EQ(toTargetAddressSpace(static_cast(AS->getAddressSpace())),
+19u);
 }
 } // namespace clang


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r367026 - [clang] Remove IsDerivedFromDeathTest.DiesOnEmptyBaseName test.

2019-07-25 Thread Anton Bikineev via cfe-commits
Author: antonbikineev
Date: Thu Jul 25 08:09:37 2019
New Revision: 367026

URL: http://llvm.org/viewvc/llvm-project?rev=367026=rev
Log:
[clang] Remove IsDerivedFromDeathTest.DiesOnEmptyBaseName test.

The semantics of an empty basename passed to isDerivedFrom matchers
changed in r367022, so this test is no longer relevant.

Modified:
cfe/trunk/unittests/ASTMatchers/ASTMatchersInternalTest.cpp

Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersInternalTest.cpp?rev=367026=367025=367026=diff
==
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersInternalTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersInternalTest.cpp Thu Jul 25 
08:09:37 2019
@@ -32,13 +32,6 @@ TEST(HasNameDeathTest, DiesOnEmptyPatter
   EXPECT_TRUE(notMatches("class X {};", HasEmptyName));
 }, "");
 }
-
-TEST(IsDerivedFromDeathTest, DiesOnEmptyBaseName) {
-  ASSERT_DEBUG_DEATH({
-DeclarationMatcher IsDerivedFromEmpty = cxxRecordDecl(isDerivedFrom(""));
-EXPECT_TRUE(notMatches("class X {};", IsDerivedFromEmpty));
-  }, "");
-}
 #endif
 
 TEST(ConstructVariadic, MismatchedTypes_Regression) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r367022 - [clang] Fail for empty names in is*DerivedFrom matchers.

2019-07-25 Thread Anton Bikineev via cfe-commits
Author: antonbikineev
Date: Thu Jul 25 07:48:55 2019
New Revision: 367022

URL: http://llvm.org/viewvc/llvm-project?rev=367022=rev
Log:
[clang] Fail for empty names in is*DerivedFrom matchers.

Differential Revision: https://reviews.llvm.org/D65279

Modified:
cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp

Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=367022=367021=367022=diff
==
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Thu Jul 25 07:48:55 2019
@@ -2639,7 +2639,8 @@ AST_MATCHER_P(CXXRecordDecl, isDerivedFr
 
 /// Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
 AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, std::string, BaseName, 1) 
{
-  assert(!BaseName.empty());
+  if (BaseName.empty())
+return false;
   return isDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
 }
 
@@ -2655,7 +2656,8 @@ AST_MATCHER_P_OVERLOAD(CXXRecordDecl, is
 /// \c isSameOrDerivedFrom(hasName(...)).
 AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string,
BaseName, 1) {
-  assert(!BaseName.empty());
+  if (BaseName.empty())
+return false;
   return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
 }
 
@@ -2687,7 +2689,8 @@ AST_MATCHER_P_OVERLOAD(CXXRecordDecl, is
 /// Overloaded method as shortcut for \c isDirectlyDerivedFrom(hasName(...)).
 AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDirectlyDerivedFrom, std::string,
BaseName, 1) {
-  assert(!BaseName.empty());
+  if (BaseName.empty())
+return false;
   return isDirectlyDerivedFrom(hasName(BaseName))
   .matches(Node, Finder, Builder);
 }

Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp?rev=367022=367021=367022=diff
==
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Thu Jul 25 
07:48:55 2019
@@ -566,6 +566,13 @@ TEST(DeclarationMatcher, ClassIsDerived)
 cxxRecordDecl(isDerivedFrom(namedDecl(hasName("X"));
 }
 
+TEST(DeclarationMatcher, IsDerivedFromEmptyName) {
+  const char *const Code = "class X {}; class Y : public X {};";
+  EXPECT_TRUE(notMatches(Code, cxxRecordDecl(isDerivedFrom("";
+  EXPECT_TRUE(notMatches(Code, cxxRecordDecl(isDirectlyDerivedFrom("";
+  EXPECT_TRUE(notMatches(Code, cxxRecordDecl(isSameOrDerivedFrom("";
+}
+
 TEST(DeclarationMatcher, IsLambda) {
   const auto IsLambda = cxxMethodDecl(ofClass(cxxRecordDecl(isLambda(;
   EXPECT_TRUE(matches("auto x = []{};", IsLambda));


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r367010 - [clang] Add isDirectlyDerivedFrom AST matcher.

2019-07-25 Thread Anton Bikineev via cfe-commits
Author: antonbikineev
Date: Thu Jul 25 04:54:13 2019
New Revision: 367010

URL: http://llvm.org/viewvc/llvm-project?rev=367010=rev
Log:
[clang] Add isDirectlyDerivedFrom AST matcher.

Differential Revision: https://reviews.llvm.org/D65092

Modified:
cfe/trunk/docs/LibASTMatchersReference.html
cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp
cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp

Modified: cfe/trunk/docs/LibASTMatchersReference.html
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=367010=367009=367010=diff
==
--- cfe/trunk/docs/LibASTMatchersReference.html (original)
+++ cfe/trunk/docs/LibASTMatchersReference.html Thu Jul 25 04:54:13 2019
@@ -2581,6 +2581,11 @@ class y;
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html;>CXXRecordDeclisDirectlyDerivedFromstd::string
 BaseName
+Overloaded 
method as shortcut for isDirectlyDerivedFrom(hasName(...)).
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html;>CXXRecordDeclisExplicitTemplateSpecialization
 Matches explicit template 
specializations of function, class, or
 static member variable template instantiations.
@@ -5252,6 +5257,26 @@ Example matches Y, Z, C (Base == hasName
   class X;
   class Y : public X {};  // directly derived
   class Z : public Y {};  // indirectly derived
+  typedef X A;
+  typedef A B;
+  class C : public B {};  // derived from a typedef of X
+
+In the following example, Bar matches isDerivedFrom(hasName("X")):
+  class Foo;
+  typedef Foo X;
+  class Bar : public Foo {};  // derived from a type that X is a typedef of
+
+
+
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html;>CXXRecordDeclisDirectlyDerivedFromMatcherhttps://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html;>NamedDecl
 Base
+Matches C++ 
classes that are directly derived from a class matching Base.
+
+Note that a class is not considered to be derived from itself.
+
+Example matches Y, C (Base == hasName("X"))
+  class X;
+  class Y : public X {};  // directly derived
+  class Z : public Y {};  // indirectly derived
   typedef X A;
   typedef A B;
   class C : public B {};  // derived from a typedef of X

Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=367010=367009=367010=diff
==
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Thu Jul 25 04:54:13 2019
@@ -2634,7 +2634,7 @@ hasOverloadedOperatorName(StringRef Name
 /// \endcode
 AST_MATCHER_P(CXXRecordDecl, isDerivedFrom,
   internal::Matcher, Base) {
-  return Finder->classIsDerivedFrom(, Base, Builder);
+  return Finder->classIsDerivedFrom(, Base, Builder, /*Directly=*/false);
 }
 
 /// Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
@@ -2659,6 +2659,38 @@ AST_MATCHER_P_OVERLOAD(CXXRecordDecl, is
   return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
 }
 
+/// Matches C++ classes that are directly derived from a class matching \c 
Base.
+///
+/// Note that a class is not considered to be derived from itself.
+///
+/// Example matches Y, C (Base == hasName("X"))
+/// \code
+///   class X;
+///   class Y : public X {};  // directly derived
+///   class Z : public Y {};  // indirectly derived
+///   typedef X A;
+///   typedef A B;
+///   class C : public B {};  // derived from a typedef of X
+/// \endcode
+///
+/// In the following example, Bar matches isDerivedFrom(hasName("X")):
+/// \code
+///   class Foo;
+///   typedef Foo X;
+///   class Bar : public Foo {};  // derived from a type that X is a typedef of
+/// \endcode
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDirectlyDerivedFrom,
+   internal::Matcher, Base, 0) {
+  return Finder->classIsDerivedFrom(, Base, Builder, /*Directly=*/true);
+}
+
+/// Overloaded method as shortcut for \c isDirectlyDerivedFrom(hasName(...)).
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDirectlyDerivedFrom, std::string,
+   BaseName, 1) {
+  assert(!BaseName.empty());
+  return isDirectlyDerivedFrom(hasName(BaseName))
+  .matches(Node, Finder, Builder);
+}
 /// Matches the first method of a class or struct that satisfies \c
 /// InnerMatcher.
 ///

Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=367010=367009=367010=diff
==
--- 

[PATCH] D26896: [libcxx] Make constexpr char_traits and char_traits

2016-11-24 Thread Anton Bikineev via cfe-commits
AntonBikineev marked 2 inline comments as done.
AntonBikineev added inline comments.



Comment at: include/__config:925
 
+#if !__has_builtin(__builtin_memcpy)
+#define _LIBCPP_HAS_NO_BUILTIN_MEMCPY

EricWF wrote:
> What about GCC? Surely it implements some if not most of these.
Thanks, good point. I've done it in the same way as it is done for 
__buitin_addressof. On the other hand, gcc has an option -fno-builtin to 
disable them. That way it *won't* compile. I try to stick to the current 
solution though.



Comment at: include/__string:213
 
-static inline int compare(const char_type* __s1, const char_type* __s2, 
size_t __n) _NOEXCEPT
-{return __n == 0 ? 0 : memcmp(__s1, __s2, __n);}
-static inline size_t length(const char_type* __s)  _NOEXCEPT {return 
strlen(__s);}
-static inline const char_type* find(const char_type* __s, size_t __n, 
const char_type& __a) _NOEXCEPT
-{return __n == 0 ? NULL : (const char_type*) memchr(__s, 
to_int_type(__a), __n);}
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
+static inline constexpr int

EricWF wrote:
> wow. This is #ifdef hell. Please find a way to do it with less (or hopefully 
> no) conditional compilation blocks.
yep, this is generic hell. I want to cover as many cases as possible, i.e. 
combinations of (is_constexpr x has_builtin_xxx) for every function. I'm open 
to suggestions


https://reviews.llvm.org/D26896



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26896: [libcxx] Make constexpr char_traits and char_traits

2016-11-24 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 79218.
AntonBikineev added a comment.

Support gcc's __builtin_memcpy, memchr, strlen


https://reviews.llvm.org/D26896

Files:
  include/__config
  include/__string
  
test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char/assign2.pass.cpp
  
test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char/compare.pass.cpp
  
test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char/find.pass.cpp
  
test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char/length.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opeq.string_view.pointer.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opeq.string_view.string_view.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opge.string_view.pointer.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opge.string_view.string_view.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opgt.string_view.pointer.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opgt.string_view.string_view.pass.cpp
  
test/std/strings/string.view/string.view.comparison/ople.string_view.pointer.pass.cpp
  
test/std/strings/string.view/string.view.comparison/ople.string_view.string_view.pass.cpp
  
test/std/strings/string.view/string.view.comparison/oplt.string_view.pointer.pass.cpp
  
test/std/strings/string.view/string.view.comparison/oplt.string_view.string_view.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opne.string_view.pointer.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opne.string_view.string_view.pass.cpp
  test/std/strings/string.view/string.view.cons/from_literal.pass.cpp
  test/std/strings/string.view/string.view.find/find_char_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_first_not_of_char_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_first_not_of_pointer_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_first_not_of_pointer_size_size.pass.cpp
  test/std/strings/string.view/string.view.find/find_first_of_char_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_first_of_pointer_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_first_of_pointer_size_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_last_not_of_char_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_last_not_of_pointer_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_last_not_of_pointer_size_size.pass.cpp
  test/std/strings/string.view/string.view.find/find_last_of_char_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_last_of_pointer_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_last_of_pointer_size_size.pass.cpp
  test/std/strings/string.view/string.view.find/find_pointer_size.pass.cpp
  test/std/strings/string.view/string.view.find/find_pointer_size_size.pass.cpp
  test/std/strings/string.view/string.view.find/find_string_view_size.pass.cpp
  test/std/strings/string.view/string.view.find/rfind_char_size.pass.cpp
  test/std/strings/string.view/string.view.find/rfind_pointer_size.pass.cpp
  test/std/strings/string.view/string.view.find/rfind_pointer_size_size.pass.cpp
  test/std/strings/string.view/string.view.find/rfind_string_view_size.pass.cpp
  test/std/strings/string.view/string.view.ops/compare.pointer.pass.cpp
  test/std/strings/string.view/string.view.ops/compare.pointer_size.pass.cpp
  test/std/strings/string.view/string.view.ops/compare.size_size_sv.pass.cpp
  
test/std/strings/string.view/string.view.ops/compare.size_size_sv_pointer_size.pass.cpp
  
test/std/strings/string.view/string.view.ops/compare.size_size_sv_size_size.pass.cpp
  test/std/strings/string.view/string.view.ops/compare.sv.pass.cpp

Index: test/std/strings/string.view/string.view.ops/compare.sv.pass.cpp
===
--- test/std/strings/string.view/string.view.ops/compare.sv.pass.cpp
+++ test/std/strings/string.view/string.view.ops/compare.sv.pass.cpp
@@ -119,4 +119,17 @@
 static_assert ( sv2.compare(sv3)  < 0, "" );
 }
 #endif
+
+#if TEST_STD_VER > 14
+{
+typedef std::string_view SV;
+constexpr SV  sv1 { "abcde", 5 };
+constexpr SV  sv2 { "abcde", 5 };
+constexpr SV  sv3 { "edcba0", 6 };
+static_assert ( sv1.compare(sv2) == 0, "" );
+static_assert ( sv2.compare(sv1) == 0, "" );
+static_assert ( sv3.compare(sv2)  > 0, "" );
+static_assert ( sv2.compare(sv3)  < 0, "" );
+}
+#endif
 }
Index: test/std/strings/string.view/string.view.ops/compare.size_size_sv_size_size.pass.cpp
===
--- test/std/strings/string.view/string.view.ops/compare.size_size_sv_size_size.pass.cpp
+++ 

[PATCH] D26896: [libcxx] Make constexpr char_traits and char_traits

2016-11-21 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 78773.

https://reviews.llvm.org/D26896

Files:
  include/__config
  include/__string
  
test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char/assign2.pass.cpp
  
test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char/compare.pass.cpp
  
test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char/find.pass.cpp
  
test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char/length.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opeq.string_view.pointer.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opeq.string_view.string_view.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opge.string_view.pointer.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opge.string_view.string_view.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opgt.string_view.pointer.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opgt.string_view.string_view.pass.cpp
  
test/std/strings/string.view/string.view.comparison/ople.string_view.pointer.pass.cpp
  
test/std/strings/string.view/string.view.comparison/ople.string_view.string_view.pass.cpp
  
test/std/strings/string.view/string.view.comparison/oplt.string_view.pointer.pass.cpp
  
test/std/strings/string.view/string.view.comparison/oplt.string_view.string_view.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opne.string_view.pointer.pass.cpp
  
test/std/strings/string.view/string.view.comparison/opne.string_view.string_view.pass.cpp
  test/std/strings/string.view/string.view.cons/from_literal.pass.cpp
  test/std/strings/string.view/string.view.find/find_char_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_first_not_of_char_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_first_not_of_pointer_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_first_not_of_pointer_size_size.pass.cpp
  test/std/strings/string.view/string.view.find/find_first_of_char_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_first_of_pointer_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_first_of_pointer_size_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_last_not_of_char_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_last_not_of_pointer_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_last_not_of_pointer_size_size.pass.cpp
  test/std/strings/string.view/string.view.find/find_last_of_char_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_last_of_pointer_size.pass.cpp
  
test/std/strings/string.view/string.view.find/find_last_of_pointer_size_size.pass.cpp
  test/std/strings/string.view/string.view.find/find_pointer_size.pass.cpp
  test/std/strings/string.view/string.view.find/find_pointer_size_size.pass.cpp
  test/std/strings/string.view/string.view.find/find_string_view_size.pass.cpp
  test/std/strings/string.view/string.view.find/rfind_char_size.pass.cpp
  test/std/strings/string.view/string.view.find/rfind_pointer_size.pass.cpp
  test/std/strings/string.view/string.view.find/rfind_pointer_size_size.pass.cpp
  test/std/strings/string.view/string.view.find/rfind_string_view_size.pass.cpp
  test/std/strings/string.view/string.view.ops/compare.pointer.pass.cpp
  test/std/strings/string.view/string.view.ops/compare.pointer_size.pass.cpp
  test/std/strings/string.view/string.view.ops/compare.size_size_sv.pass.cpp
  
test/std/strings/string.view/string.view.ops/compare.size_size_sv_pointer_size.pass.cpp
  
test/std/strings/string.view/string.view.ops/compare.size_size_sv_size_size.pass.cpp
  test/std/strings/string.view/string.view.ops/compare.sv.pass.cpp

Index: test/std/strings/string.view/string.view.ops/compare.sv.pass.cpp
===
--- test/std/strings/string.view/string.view.ops/compare.sv.pass.cpp
+++ test/std/strings/string.view/string.view.ops/compare.sv.pass.cpp
@@ -119,4 +119,17 @@
 static_assert ( sv2.compare(sv3)  < 0, "" );
 }
 #endif
+
+#if TEST_STD_VER > 14
+{
+typedef std::string_view SV;
+constexpr SV  sv1 { "abcde", 5 };
+constexpr SV  sv2 { "abcde", 5 };
+constexpr SV  sv3 { "edcba0", 6 };
+static_assert ( sv1.compare(sv2) == 0, "" );
+static_assert ( sv2.compare(sv1) == 0, "" );
+static_assert ( sv3.compare(sv2)  > 0, "" );
+static_assert ( sv2.compare(sv3)  < 0, "" );
+}
+#endif
 }
Index: test/std/strings/string.view/string.view.ops/compare.size_size_sv_size_size.pass.cpp
===
--- test/std/strings/string.view/string.view.ops/compare.size_size_sv_size_size.pass.cpp
+++ test/std/strings/string.view/string.view.ops/compare.size_size_sv_size_size.pass.cpp
@@ -5844,4 +5844,14 @@
 

[PATCH] D26829: [clang] Allow lexer to handle string_view literals

2016-11-21 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 78739.

https://reviews.llvm.org/D26829

Files:
  include/clang/Lex/LiteralSupport.h
  lib/Lex/Lexer.cpp
  lib/Lex/LiteralSupport.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/SemaCXX/cxx1z-user-defined-literals.cpp


Index: test/SemaCXX/cxx1z-user-defined-literals.cpp
===
--- test/SemaCXX/cxx1z-user-defined-literals.cpp
+++ test/SemaCXX/cxx1z-user-defined-literals.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++1z %s -include %s -verify
+
+#ifndef INCLUDED
+#define INCLUDED
+
+#pragma clang system_header
+namespace std {
+  using size_t = decltype(sizeof(0));
+
+  struct string_view {};
+  string_view operator""sv(const char*, size_t);
+}
+
+#else
+
+using namespace std;
+string_view s = "foo"sv;
+const char* p = "bar"sv; // expected-error {{no viable conversion}}
+char error = 'x'sv; // expected-error {{invalid suffix}} expected-error 
{{expected ';'}}
+
+#endif
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -12908,7 +12908,7 @@
 //   Literal suffix identifiers that do not start with an underscore
 //   are reserved for future standardization.
 Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved)
-  << NumericLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
+  << StringLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
   }
 
   return false;
Index: lib/Lex/LiteralSupport.cpp
===
--- lib/Lex/LiteralSupport.cpp
+++ lib/Lex/LiteralSupport.cpp
@@ -1708,3 +1708,12 @@
 
   return SpellingPtr-SpellingStart;
 }
+
+/// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved
+/// suffixes as ud-suffixes, because the diagnostic experience is better if we
+/// treat it as an invalid suffix.
+bool StringLiteralParser::isValidUDSuffix(const LangOptions ,
+  StringRef Suffix) {
+  return NumericLiteralParser::isValidUDSuffix(LangOpts, Suffix) ||
+ Suffix == "sv";
+}
Index: include/clang/Lex/LiteralSupport.h
===
--- include/clang/Lex/LiteralSupport.h
+++ include/clang/Lex/LiteralSupport.h
@@ -259,6 +259,8 @@
 return UDSuffixOffset;
   }
 
+  static bool isValidUDSuffix(const LangOptions , StringRef Suffix);
+
 private:
   void init(ArrayRef StringToks);
   bool CopyStringFragment(const Token , const char *TokBegin,
Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -1713,9 +1713,9 @@
  getLangOpts());
 if (!isIdentifierBody(Next)) {
   // End of suffix. Check whether this is on the whitelist.
-  IsUDSuffix = (Chars == 1 && Buffer[0] == 's') ||
-   NumericLiteralParser::isValidUDSuffix(
-   getLangOpts(), StringRef(Buffer, Chars));
+  const StringRef CompleteSuffix(Buffer, Chars);
+  IsUDSuffix = StringLiteralParser::isValidUDSuffix(getLangOpts(),
+CompleteSuffix);
   break;
 }
 


Index: test/SemaCXX/cxx1z-user-defined-literals.cpp
===
--- test/SemaCXX/cxx1z-user-defined-literals.cpp
+++ test/SemaCXX/cxx1z-user-defined-literals.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++1z %s -include %s -verify
+
+#ifndef INCLUDED
+#define INCLUDED
+
+#pragma clang system_header
+namespace std {
+  using size_t = decltype(sizeof(0));
+
+  struct string_view {};
+  string_view operator""sv(const char*, size_t);
+}
+
+#else
+
+using namespace std;
+string_view s = "foo"sv;
+const char* p = "bar"sv; // expected-error {{no viable conversion}}
+char error = 'x'sv; // expected-error {{invalid suffix}} expected-error {{expected ';'}}
+
+#endif
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -12908,7 +12908,7 @@
 //   Literal suffix identifiers that do not start with an underscore
 //   are reserved for future standardization.
 Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved)
-  << NumericLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
+  << StringLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
   }
 
   return false;
Index: lib/Lex/LiteralSupport.cpp
===
--- lib/Lex/LiteralSupport.cpp
+++ lib/Lex/LiteralSupport.cpp
@@ -1708,3 +1708,12 @@
 
   return SpellingPtr-SpellingStart;
 }
+
+/// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved
+/// suffixes as ud-suffixes, because the 

[PATCH] D26829: [clang] Allow lexer to handle string_view literals

2016-11-20 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 78654.
AntonBikineev added a comment.

Richard, thanks, I addressed your comments.


https://reviews.llvm.org/D26829

Files:
  include/clang/Lex/LiteralSupport.h
  lib/Lex/Lexer.cpp
  lib/Lex/LiteralSupport.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/SemaCXX/cxx1z-user-defined-literals.cpp


Index: test/SemaCXX/cxx1z-user-defined-literals.cpp
===
--- test/SemaCXX/cxx1z-user-defined-literals.cpp
+++ test/SemaCXX/cxx1z-user-defined-literals.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++1z %s -include %s -verify
+
+#ifndef INCLUDED
+#define INCLUDED
+
+#pragma clang system_header
+namespace std {
+  using size_t = decltype(sizeof(0));
+
+  struct string_view {};
+  string_view operator""sv(const char*, size_t);
+}
+
+#else
+
+using namespace std;
+string_view s = "foo"sv;
+const char* p = "bar"sv; // expected-error {{no viable conversion}}
+char error = 'x'sv; // expected-error {{invalid suffix}} expected-error 
{{expected ';'}}
+
+#endif
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -12908,7 +12908,7 @@
 //   Literal suffix identifiers that do not start with an underscore
 //   are reserved for future standardization.
 Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved)
-  << NumericLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
+  << StringLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
   }
 
   return false;
Index: lib/Lex/LiteralSupport.cpp
===
--- lib/Lex/LiteralSupport.cpp
+++ lib/Lex/LiteralSupport.cpp
@@ -1708,3 +1708,12 @@
 
   return SpellingPtr-SpellingStart;
 }
+
+/// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved
+/// suffixes as ud-suffixes, because the diagnostic experience is better if we
+/// treat it as an invalid suffix.
+bool StringLiteralParser::isValidUDSuffix(const LangOptions ,
+  StringRef Suffix) {
+  return NumericLiteralParser::isValidUDSuffix(LangOpts, Suffix) ||
+ Suffix == "sv";
+}
Index: include/clang/Lex/LiteralSupport.h
===
--- include/clang/Lex/LiteralSupport.h
+++ include/clang/Lex/LiteralSupport.h
@@ -259,6 +259,8 @@
 return UDSuffixOffset;
   }
 
+  static bool isValidUDSuffix(const LangOptions , StringRef Suffix);
+
 private:
   void init(ArrayRef StringToks);
   bool CopyStringFragment(const Token , const char *TokBegin,
Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -1713,9 +1713,10 @@
  getLangOpts());
 if (!isIdentifierBody(Next)) {
   // End of suffix. Check whether this is on the whitelist.
-  IsUDSuffix = (Chars == 1 && Buffer[0] == 's') ||
-   NumericLiteralParser::isValidUDSuffix(
-   getLangOpts(), StringRef(Buffer, Chars));
+  const StringRef CompleteSuffix(Buffer, Chars);
+  const LangOptions  = getLangOpts();
+  IsUDSuffix =
+  StringLiteralParser::isValidUDSuffix(LangOpts, CompleteSuffix);
   break;
 }
 


Index: test/SemaCXX/cxx1z-user-defined-literals.cpp
===
--- test/SemaCXX/cxx1z-user-defined-literals.cpp
+++ test/SemaCXX/cxx1z-user-defined-literals.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++1z %s -include %s -verify
+
+#ifndef INCLUDED
+#define INCLUDED
+
+#pragma clang system_header
+namespace std {
+  using size_t = decltype(sizeof(0));
+
+  struct string_view {};
+  string_view operator""sv(const char*, size_t);
+}
+
+#else
+
+using namespace std;
+string_view s = "foo"sv;
+const char* p = "bar"sv; // expected-error {{no viable conversion}}
+char error = 'x'sv; // expected-error {{invalid suffix}} expected-error {{expected ';'}}
+
+#endif
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -12908,7 +12908,7 @@
 //   Literal suffix identifiers that do not start with an underscore
 //   are reserved for future standardization.
 Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved)
-  << NumericLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
+  << StringLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
   }
 
   return false;
Index: lib/Lex/LiteralSupport.cpp
===
--- lib/Lex/LiteralSupport.cpp
+++ lib/Lex/LiteralSupport.cpp
@@ -1708,3 +1708,12 @@
 
   return SpellingPtr-SpellingStart;
 }
+
+/// Determine whether a suffix is a valid 

[PATCH] D26829: [clang] Allow lexer to handle string_view literals

2016-11-19 Thread Anton Bikineev via cfe-commits
AntonBikineev added inline comments.



Comment at: lib/Lex/LiteralSupport.cpp:1716-1717
+StringLiteralParser::UDSuffixResult
+StringLiteralParser::isValidUDSuffix(const LangOptions ,
+ StringRef Suffix) {
+  if (!LangOpts.CPlusPlus11 || Suffix.empty())

rsmith wrote:
> Just make this call `NumericLiteralParser::isValidUDSuffix` and then check 
> for the `sv` case. All the numeric suffixes are also valid string literal 
> suffixes for the form `operator""suffix`.
This makes sense for the call sites we currently have.
> All the numeric suffixes are also valid string literal suffixes for the form 
> operator""suffix.
Don't really understand this part. It seems inconsistent if one calls, say,
``` StringLiteralParser::isValidUDSuffix(LangOpts(), "if")  ```
 and gets
```true```


https://reviews.llvm.org/D26829



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26829: [clang] Allow lexer to handle string_view literals

2016-11-18 Thread Anton Bikineev via cfe-commits
AntonBikineev added a comment.

In https://reviews.llvm.org/D26829#599906, @malcolm.parsons wrote:

> Does `Sema::CheckLiteralOperatorDeclaration` need to check 
> `StringLiteralParser::isValidUDSuffix`?


Thanks, nice point! Just addressed it.


https://reviews.llvm.org/D26829



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26829: [clang] Allow lexer to handle string_view literals

2016-11-18 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 78602.

https://reviews.llvm.org/D26829

Files:
  include/clang/Basic/DiagnosticLexKinds.td
  include/clang/Lex/LiteralSupport.h
  lib/Lex/Lexer.cpp
  lib/Lex/LiteralSupport.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/SemaCXX/cxx1z-user-defined-literals.cpp

Index: test/SemaCXX/cxx1z-user-defined-literals.cpp
===
--- test/SemaCXX/cxx1z-user-defined-literals.cpp
+++ test/SemaCXX/cxx1z-user-defined-literals.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++1z %s -include %s -verify
+
+#ifndef INCLUDED
+#define INCLUDED
+
+#pragma clang system_header
+namespace std {
+  using size_t = decltype(sizeof(0));
+
+  struct string_view {};
+  string_view operator""sv(const char*, size_t);
+}
+
+#else
+
+using namespace std;
+string_view s = "foo"sv;
+const char* p = "bar"sv; // expected-error {{no viable conversion}}
+char error = 'x'sv; // expected-error {{invalid suffix}} expected-error {{expected ';'}}
+
+#endif
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -12904,11 +12904,15 @@
   StringRef LiteralName
 = FnDecl->getDeclName().getCXXLiteralIdentifier()->getName();
   if (LiteralName[0] != '_') {
+bool MoreMessage =
+NumericLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName) ||
+(StringLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName) ==
+ StringLiteralParser::UDSuffixResult::Valid);
 // C++11 [usrlit.suffix]p1:
 //   Literal suffix identifiers that do not start with an underscore
 //   are reserved for future standardization.
 Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved)
-  << NumericLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
+  << std::move(MoreMessage);
   }
 
   return false;
Index: lib/Lex/LiteralSupport.cpp
===
--- lib/Lex/LiteralSupport.cpp
+++ lib/Lex/LiteralSupport.cpp
@@ -1708,3 +1708,28 @@
 
   return SpellingPtr-SpellingStart;
 }
+
+/// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved
+/// suffixes as ud-suffixes, because the diagnostic experience is better if we
+/// treat it as an invalid suffix.
+StringLiteralParser::UDSuffixResult
+StringLiteralParser::isValidUDSuffix(const LangOptions ,
+ StringRef Suffix) {
+  if (!LangOpts.CPlusPlus11 || Suffix.empty())
+return UDSuffixResult::Invalid;
+
+  // By C++11 [lex.ext]p10, ud-suffixes starting with an '_' are always valid.
+  if (Suffix[0] == '_')
+return UDSuffixResult::Valid;
+
+  // In C++11, there are no library suffixes.
+  if (!LangOpts.CPlusPlus14)
+return UDSuffixResult::Invalid;
+
+  // C++1z adds "sv" literals
+  if (Suffix == "sv")
+return LangOpts.CPlusPlus1z ? UDSuffixResult::Valid
+: UDSuffixResult::SVIncompatible;
+
+  return Suffix == "s" ? UDSuffixResult::Valid : UDSuffixResult::Invalid;
+}
Index: include/clang/Lex/LiteralSupport.h
===
--- include/clang/Lex/LiteralSupport.h
+++ include/clang/Lex/LiteralSupport.h
@@ -259,6 +259,13 @@
 return UDSuffixOffset;
   }
 
+  enum class UDSuffixResult : uint8_t {
+Valid, Invalid, SVIncompatible
+  };
+
+  static UDSuffixResult isValidUDSuffix(const LangOptions ,
+StringRef Suffix);
+
 private:
   void init(ArrayRef StringToks);
   bool CopyStringFragment(const Token , const char *TokBegin,
Index: include/clang/Basic/DiagnosticLexKinds.td
===
--- include/clang/Basic/DiagnosticLexKinds.td
+++ include/clang/Basic/DiagnosticLexKinds.td
@@ -186,6 +186,8 @@
   "hexadecimal floating literals are incompatible with "
   "C++ standards before C++1z">,
   InGroup, DefaultIgnore;
+def err_cxx1z_string_view_literal : Error<
+  "string_view literals are a C++1z feature">;
 def ext_binary_literal : Extension<
   "binary integer literals are a GNU extension">, InGroup;
 def ext_binary_literal_cxx14 : Extension<
Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -1697,6 +1697,8 @@
   // likely to be a ud-suffix than a macro, however, and accept that.
   if (!Consumed) {
 bool IsUDSuffix = false;
+StringLiteralParser::UDSuffixResult IsStringUDSuffix =
+StringLiteralParser::UDSuffixResult::Invalid;
 if (C == '_')
   IsUDSuffix = true;
 else if (IsStringLiteral && getLangOpts().CPlusPlus14) {
@@ -1713,9 +1715,18 @@
  getLangOpts());
 if (!isIdentifierBody(Next)) {
   // End of suffix. Check whether this is on the whitelist.
-  IsUDSuffix = (Chars == 1 && Buffer[0] == 's') ||

[PATCH] D26830: [libcxx] Add string_view literals

2016-11-18 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 78532.
AntonBikineev marked an inline comment as done.
AntonBikineev added a comment.

Fixing typos...


https://reviews.llvm.org/D26830

Files:
  include/string_view
  test/std/strings/string.view/string.view.literals/literal.pass.cpp
  test/std/strings/string.view/string.view.literals/literal1.fail.cpp
  test/std/strings/string.view/string.view.literals/literal1.pass.cpp
  test/std/strings/string.view/string.view.literals/literal2.fail.cpp
  test/std/strings/string.view/string.view.literals/literal2.pass.cpp
  test/std/strings/string.view/string.view.literals/literal3.pass.cpp

Index: test/std/strings/string.view/string.view.literals/literal3.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal3.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std;
+
+string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal2.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal2.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std::literals::string_view_literals;
+
+std::string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal2.fail.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal2.fail.cpp
@@ -0,0 +1,19 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+std::string_view foo  =   ""sv;  // should fail w/conversion operator not found
+}
Index: test/std/strings/string.view/string.view.literals/literal1.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal1.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std::literals;
+
+std::string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal1.fail.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal1.fail.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using std::string_view;
+
+string_view foo  =   ""sv;  // should fail w/conversion operator not found
+}
Index: test/std/strings/string.view/string.view.literals/literal.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal.pass.cpp
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+//===--===//
+//
+//   

[PATCH] D26829: [clang] Allow lexer to handle string_view literals

2016-11-18 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 78523.
AntonBikineev added a comment.

Just added a small test case


https://reviews.llvm.org/D26829

Files:
  include/clang/Basic/DiagnosticLexKinds.td
  include/clang/Lex/LiteralSupport.h
  lib/Lex/Lexer.cpp
  lib/Lex/LiteralSupport.cpp
  test/SemaCXX/cxx1z-user-defined-literals.cpp

Index: test/SemaCXX/cxx1z-user-defined-literals.cpp
===
--- test/SemaCXX/cxx1z-user-defined-literals.cpp
+++ test/SemaCXX/cxx1z-user-defined-literals.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++1z %s -include %s -verify
+
+#ifndef INCLUDED
+#define INCLUDED
+
+#pragma clang system_header
+namespace std {
+  using size_t = decltype(sizeof(0));
+
+  struct string_view {};
+  string_view operator""sv(const char*, size_t);
+}
+
+#else
+
+using namespace std;
+string_view s = "foo"sv;
+const char* p = "bar"sv; // expected-error {{no viable conversion}}
+char error = 'x'sv; // expected-error {{invalid suffix}} expected-error {{expected ';'}}
+
+#endif
Index: lib/Lex/LiteralSupport.cpp
===
--- lib/Lex/LiteralSupport.cpp
+++ lib/Lex/LiteralSupport.cpp
@@ -1708,3 +1708,28 @@
 
   return SpellingPtr-SpellingStart;
 }
+
+/// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved
+/// suffixes as ud-suffixes, because the diagnostic experience is better if we
+/// treat it as an invalid suffix.
+StringLiteralParser::UDSuffixResult
+StringLiteralParser::isValidUDSuffix(const LangOptions ,
+ StringRef Suffix) {
+  if (!LangOpts.CPlusPlus11 || Suffix.empty())
+return UDSuffixResult::Invalid;
+
+  // By C++11 [lex.ext]p10, ud-suffixes starting with an '_' are always valid.
+  if (Suffix[0] == '_')
+return UDSuffixResult::Valid;
+
+  // In C++11, there are no library suffixes.
+  if (!LangOpts.CPlusPlus14)
+return UDSuffixResult::Invalid;
+
+  // C++1z adds "sv" literals
+  if (Suffix == "sv")
+return LangOpts.CPlusPlus1z ? UDSuffixResult::Valid
+: UDSuffixResult::SVIncompatible;
+
+  return Suffix == "s" ? UDSuffixResult::Valid : UDSuffixResult::Invalid;
+}
Index: include/clang/Lex/LiteralSupport.h
===
--- include/clang/Lex/LiteralSupport.h
+++ include/clang/Lex/LiteralSupport.h
@@ -259,6 +259,13 @@
 return UDSuffixOffset;
   }
 
+  enum class UDSuffixResult : uint8_t {
+Valid, Invalid, SVIncompatible
+  };
+
+  static UDSuffixResult isValidUDSuffix(const LangOptions ,
+StringRef Suffix);
+
 private:
   void init(ArrayRef StringToks);
   bool CopyStringFragment(const Token , const char *TokBegin,
Index: include/clang/Basic/DiagnosticLexKinds.td
===
--- include/clang/Basic/DiagnosticLexKinds.td
+++ include/clang/Basic/DiagnosticLexKinds.td
@@ -186,6 +186,8 @@
   "hexadecimal floating literals are incompatible with "
   "C++ standards before C++1z">,
   InGroup, DefaultIgnore;
+def err_cxx1z_string_view_literal : Error<
+  "string_view literals are a C++1z feature">;
 def ext_binary_literal : Extension<
   "binary integer literals are a GNU extension">, InGroup;
 def ext_binary_literal_cxx14 : Extension<
Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -1697,6 +1697,8 @@
   // likely to be a ud-suffix than a macro, however, and accept that.
   if (!Consumed) {
 bool IsUDSuffix = false;
+StringLiteralParser::UDSuffixResult IsStringUDSuffix =
+StringLiteralParser::UDSuffixResult::Invalid;
 if (C == '_')
   IsUDSuffix = true;
 else if (IsStringLiteral && getLangOpts().CPlusPlus14) {
@@ -1713,9 +1715,18 @@
  getLangOpts());
 if (!isIdentifierBody(Next)) {
   // End of suffix. Check whether this is on the whitelist.
-  IsUDSuffix = (Chars == 1 && Buffer[0] == 's') ||
-   NumericLiteralParser::isValidUDSuffix(
-   getLangOpts(), StringRef(Buffer, Chars));
+  const StringRef CompleteSuffix(Buffer, Chars);
+  const LangOptions  = getLangOpts();
+  // First, check if the suffix is a numeric suffix (s,sv)
+  IsUDSuffix =
+  NumericLiteralParser::isValidUDSuffix(LangOpts, CompleteSuffix);
+  // If it is not, check for a string suffix
+  if (!IsUDSuffix) {
+IsStringUDSuffix =
+StringLiteralParser::isValidUDSuffix(LangOpts, CompleteSuffix);
+IsUDSuffix =
+IsStringUDSuffix == StringLiteralParser::UDSuffixResult::Valid;
+  }
   break;
 }
 
@@ -1729,11 +1740,18 @@
 }
 
 if (!IsUDSuffix) {
-  if (!isLexingRawMode())
-Diag(CurPtr, 

[PATCH] D26829: [clang] Allow lexer to handle string_view literals

2016-11-18 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 78511.

https://reviews.llvm.org/D26829

Files:
  include/clang/Basic/DiagnosticLexKinds.td
  include/clang/Lex/LiteralSupport.h
  lib/Lex/Lexer.cpp
  lib/Lex/LiteralSupport.cpp

Index: lib/Lex/LiteralSupport.cpp
===
--- lib/Lex/LiteralSupport.cpp
+++ lib/Lex/LiteralSupport.cpp
@@ -1708,3 +1708,28 @@
 
   return SpellingPtr-SpellingStart;
 }
+
+/// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved
+/// suffixes as ud-suffixes, because the diagnostic experience is better if we
+/// treat it as an invalid suffix.
+StringLiteralParser::UDSuffixResult
+StringLiteralParser::isValidUDSuffix(const LangOptions ,
+ StringRef Suffix) {
+  if (!LangOpts.CPlusPlus11 || Suffix.empty())
+return UDSuffixResult::Invalid;
+
+  // By C++11 [lex.ext]p10, ud-suffixes starting with an '_' are always valid.
+  if (Suffix[0] == '_')
+return UDSuffixResult::Valid;
+
+  // In C++11, there are no library suffixes.
+  if (!LangOpts.CPlusPlus14)
+return UDSuffixResult::Invalid;
+
+  // C++1z adds "sv" literals
+  if (Suffix == "sv")
+return LangOpts.CPlusPlus1z ? UDSuffixResult::Valid
+: UDSuffixResult::SVIncompatible;
+
+  return Suffix == "s" ? UDSuffixResult::Valid : UDSuffixResult::Invalid;
+}
Index: include/clang/Lex/LiteralSupport.h
===
--- include/clang/Lex/LiteralSupport.h
+++ include/clang/Lex/LiteralSupport.h
@@ -259,6 +259,13 @@
 return UDSuffixOffset;
   }
 
+  enum class UDSuffixResult : uint8_t {
+Valid, Invalid, SVIncompatible
+  };
+
+  static UDSuffixResult isValidUDSuffix(const LangOptions ,
+StringRef Suffix);
+
 private:
   void init(ArrayRef StringToks);
   bool CopyStringFragment(const Token , const char *TokBegin,
Index: include/clang/Basic/DiagnosticLexKinds.td
===
--- include/clang/Basic/DiagnosticLexKinds.td
+++ include/clang/Basic/DiagnosticLexKinds.td
@@ -186,6 +186,8 @@
   "hexadecimal floating literals are incompatible with "
   "C++ standards before C++1z">,
   InGroup, DefaultIgnore;
+def err_cxx1z_string_view_literal : Error<
+  "string_view literals are a C++1z feature">;
 def ext_binary_literal : Extension<
   "binary integer literals are a GNU extension">, InGroup;
 def ext_binary_literal_cxx14 : Extension<
Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -1697,6 +1697,8 @@
   // likely to be a ud-suffix than a macro, however, and accept that.
   if (!Consumed) {
 bool IsUDSuffix = false;
+StringLiteralParser::UDSuffixResult IsStringUDSuffix =
+StringLiteralParser::UDSuffixResult::Invalid;
 if (C == '_')
   IsUDSuffix = true;
 else if (IsStringLiteral && getLangOpts().CPlusPlus14) {
@@ -1713,9 +1715,18 @@
  getLangOpts());
 if (!isIdentifierBody(Next)) {
   // End of suffix. Check whether this is on the whitelist.
-  IsUDSuffix = (Chars == 1 && Buffer[0] == 's') ||
-   NumericLiteralParser::isValidUDSuffix(
-   getLangOpts(), StringRef(Buffer, Chars));
+  const StringRef CompleteSuffix(Buffer, Chars);
+  const LangOptions  = getLangOpts();
+  // First, check if the suffix is a numeric suffix (s,sv)
+  IsUDSuffix =
+  NumericLiteralParser::isValidUDSuffix(LangOpts, CompleteSuffix);
+  // If it is not, check for a string suffix
+  if (!IsUDSuffix) {
+IsStringUDSuffix =
+StringLiteralParser::isValidUDSuffix(LangOpts, CompleteSuffix);
+IsUDSuffix =
+IsStringUDSuffix == StringLiteralParser::UDSuffixResult::Valid;
+  }
   break;
 }
 
@@ -1729,11 +1740,18 @@
 }
 
 if (!IsUDSuffix) {
-  if (!isLexingRawMode())
-Diag(CurPtr, getLangOpts().MSVCCompat
- ? diag::ext_ms_reserved_user_defined_literal
- : diag::ext_reserved_user_defined_literal)
-  << FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
+  if (!isLexingRawMode()) {
+if (IsStringUDSuffix ==
+StringLiteralParser::UDSuffixResult::SVIncompatible) {
+  Diag(CurPtr, diag::err_cxx1z_string_view_literal)
+<< FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
+} else {
+  Diag(CurPtr, getLangOpts().MSVCCompat
+   ? diag::ext_ms_reserved_user_defined_literal
+   : diag::ext_reserved_user_defined_literal)
+<< FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
+}
+  }
   return 

[PATCH] D26829: [clang] Allow lexer to handle string_view literals

2016-11-18 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 78510.

https://reviews.llvm.org/D26829

Files:
  include/clang/Basic/DiagnosticLexKinds.td
  include/clang/Lex/LiteralSupport.h
  lib/Lex/Lexer.cpp
  lib/Lex/LiteralSupport.cpp

Index: lib/Lex/LiteralSupport.cpp
===
--- lib/Lex/LiteralSupport.cpp
+++ lib/Lex/LiteralSupport.cpp
@@ -1708,3 +1708,28 @@
 
   return SpellingPtr-SpellingStart;
 }
+
+/// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved
+/// suffixes as ud-suffixes, because the diagnostic experience is better if we
+/// treat it as an invalid suffix.
+StringLiteralParser::UDSuffixResult
+StringLiteralParser::isValidUDSuffix(const LangOptions ,
+ StringRef Suffix) {
+  if (!LangOpts.CPlusPlus11 || Suffix.empty())
+return UDSuffixResult::Invalid;
+
+  // By C++11 [lex.ext]p10, ud-suffixes starting with an '_' are always valid.
+  if (Suffix[0] == '_')
+return UDSuffixResult::Valid;
+
+  // In C++11, there are no library suffixes.
+  if (!LangOpts.CPlusPlus14)
+return UDSuffixResult::Invalid;
+
+  // C++1z adds "sv" literals
+  if (Suffix == "sv")
+return LangOpts.CPlusPlus1z ? UDSuffixResult::Valid
+: UDSuffixResult::SVIncompatible;
+
+  return Suffix == "s" ? UDSuffixResult::Valid : UDSuffixResult::Invalid;
+}
Index: include/clang/Lex/LiteralSupport.h
===
--- include/clang/Lex/LiteralSupport.h
+++ include/clang/Lex/LiteralSupport.h
@@ -259,6 +259,13 @@
 return UDSuffixOffset;
   }
 
+  enum class UDSuffixResult : uint8_t {
+Valid, Invalid, SVIncompatible
+  };
+
+  static UDSuffixResult isValidUDSuffix(const LangOptions ,
+StringRef Suffix);
+
 private:
   void init(ArrayRef StringToks);
   bool CopyStringFragment(const Token , const char *TokBegin,
Index: include/clang/Basic/DiagnosticLexKinds.td
===
--- include/clang/Basic/DiagnosticLexKinds.td
+++ include/clang/Basic/DiagnosticLexKinds.td
@@ -186,6 +186,8 @@
   "hexadecimal floating literals are incompatible with "
   "C++ standards before C++1z">,
   InGroup, DefaultIgnore;
+def err_cxx1z_string_view_literal : Error<
+  "string_view literals are a C++1z feature">;
 def ext_binary_literal : Extension<
   "binary integer literals are a GNU extension">, InGroup;
 def ext_binary_literal_cxx14 : Extension<
Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -1697,6 +1697,8 @@
   // likely to be a ud-suffix than a macro, however, and accept that.
   if (!Consumed) {
 bool IsUDSuffix = false;
+StringLiteralParser::UDSuffixResult IsStringUDSuffix =
+StringLiteralParser::UDSuffixResult::Invalid;
 if (C == '_')
   IsUDSuffix = true;
 else if (IsStringLiteral && getLangOpts().CPlusPlus14) {
@@ -1713,9 +1715,18 @@
  getLangOpts());
 if (!isIdentifierBody(Next)) {
   // End of suffix. Check whether this is on the whitelist.
-  IsUDSuffix = (Chars == 1 && Buffer[0] == 's') ||
-   NumericLiteralParser::isValidUDSuffix(
-   getLangOpts(), StringRef(Buffer, Chars));
+  const StringRef CompleteSuffix = StringRef(Buffer, Chars);
+  const LangOptions  = getLangOpts();
+  // First, check if the suffix is a numeric suffix (s,sv)
+  IsUDSuffix =
+  NumericLiteralParser::isValidUDSuffix(LangOpts, CompleteSuffix);
+  // If it is not, check for a string suffix
+  if (!IsUDSuffix) {
+IsStringUDSuffix =
+StringLiteralParser::isValidUDSuffix(LangOpts, CompleteSuffix);
+IsUDSuffix =
+IsStringUDSuffix == StringLiteralParser::UDSuffixResult::Valid;
+  }
   break;
 }
 
@@ -1730,10 +1741,16 @@
 
 if (!IsUDSuffix) {
   if (!isLexingRawMode())
-Diag(CurPtr, getLangOpts().MSVCCompat
- ? diag::ext_ms_reserved_user_defined_literal
- : diag::ext_reserved_user_defined_literal)
-  << FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
+if (IsStringUDSuffix ==
+StringLiteralParser::UDSuffixResult::SVIncompatible) {
+  Diag(CurPtr, diag::err_cxx1z_string_view_literal)
+<< FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
+} else {
+  Diag(CurPtr, getLangOpts().MSVCCompat
+   ? diag::ext_ms_reserved_user_defined_literal
+   : diag::ext_reserved_user_defined_literal)
+<< FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
+}
   return CurPtr;
 }
 

[PATCH] D26829: [clang] Allow lexer to handle string_view literals

2016-11-18 Thread Anton Bikineev via cfe-commits
AntonBikineev updated the summary for this revision.
AntonBikineev updated this revision to Diff 78507.

https://reviews.llvm.org/D26829

Files:
  include/clang/Basic/DiagnosticLexKinds.td
  include/clang/Lex/LiteralSupport.h
  lib/Lex/Lexer.cpp
  lib/Lex/LiteralSupport.cpp

Index: lib/Lex/LiteralSupport.cpp
===
--- lib/Lex/LiteralSupport.cpp
+++ lib/Lex/LiteralSupport.cpp
@@ -1708,3 +1708,28 @@
 
   return SpellingPtr-SpellingStart;
 }
+
+/// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved
+/// suffixes as ud-suffixes, because the diagnostic experience is better if we
+/// treat it as an invalid suffix.
+StringLiteralParser::UDSuffixResult
+StringLiteralParser::isValidUDSuffix(const LangOptions ,
+ StringRef Suffix) {
+  if (!LangOpts.CPlusPlus11 || Suffix.empty())
+return UDSuffixResult::Invalid;
+
+  // By C++11 [lex.ext]p10, ud-suffixes starting with an '_' are always valid.
+  if (Suffix[0] == '_')
+return UDSuffixResult::Valid;
+
+  // In C++11, there are no library suffixes.
+  if (!LangOpts.CPlusPlus14)
+return UDSuffixResult::Invalid;
+
+  // C++1z adds "sv" literals
+  if (Suffix == "sv")
+return LangOpts.CPlusPlus1z ? UDSuffixResult::Valid
+: UDSuffixResult::SVIncompatible;
+
+  return Suffix == "s" ? UDSuffixResult::Valid : UDSuffixResult::Invalid;
+}
Index: include/clang/Lex/LiteralSupport.h
===
--- include/clang/Lex/LiteralSupport.h
+++ include/clang/Lex/LiteralSupport.h
@@ -259,6 +259,13 @@
 return UDSuffixOffset;
   }
 
+  enum class UDSuffixResult : uint8_t {
+Valid, Invalid, SVIncompatible
+  };
+
+  static UDSuffixResult isValidUDSuffix(const LangOptions ,
+   StringRef Suffix);
+
 private:
   void init(ArrayRef StringToks);
   bool CopyStringFragment(const Token , const char *TokBegin,
Index: include/clang/Basic/DiagnosticLexKinds.td
===
--- include/clang/Basic/DiagnosticLexKinds.td
+++ include/clang/Basic/DiagnosticLexKinds.td
@@ -186,6 +186,8 @@
   "hexadecimal floating literals are incompatible with "
   "C++ standards before C++1z">,
   InGroup, DefaultIgnore;
+def err_cxx1z_string_view_literal : Error<
+  "string_view literals are a C++1z feature">;
 def ext_binary_literal : Extension<
   "binary integer literals are a GNU extension">, InGroup;
 def ext_binary_literal_cxx14 : Extension<
Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -1697,6 +1697,8 @@
   // likely to be a ud-suffix than a macro, however, and accept that.
   if (!Consumed) {
 bool IsUDSuffix = false;
+StringLiteralParser::UDSuffixResult IsStringUDSuffix =
+StringLiteralParser::UDSuffixResult::Invalid;
 if (C == '_')
   IsUDSuffix = true;
 else if (IsStringLiteral && getLangOpts().CPlusPlus14) {
@@ -1713,9 +1715,18 @@
  getLangOpts());
 if (!isIdentifierBody(Next)) {
   // End of suffix. Check whether this is on the whitelist.
-  IsUDSuffix = (Chars == 1 && Buffer[0] == 's') ||
-   NumericLiteralParser::isValidUDSuffix(
-   getLangOpts(), StringRef(Buffer, Chars));
+  const StringRef CompleteSuffix = StringRef(Buffer, Chars);
+  const LangOptions  = getLangOpts();
+  // First, check if the suffix is a numeric suffix (s,sv)
+  IsUDSuffix =
+  NumericLiteralParser::isValidUDSuffix(LangOpts, CompleteSuffix);
+  // If it is not, check for a string suffix
+  if (!IsUDSuffix) {
+IsStringUDSuffix =
+StringLiteralParser::isValidUDSuffix(LangOpts, CompleteSuffix);
+IsUDSuffix =
+IsStringUDSuffix == StringLiteralParser::UDSuffixResult::Valid;
+  }
   break;
 }
 
@@ -1730,10 +1741,16 @@
 
 if (!IsUDSuffix) {
   if (!isLexingRawMode())
-Diag(CurPtr, getLangOpts().MSVCCompat
- ? diag::ext_ms_reserved_user_defined_literal
- : diag::ext_reserved_user_defined_literal)
-  << FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
+if (IsStringUDSuffix ==
+StringLiteralParser::UDSuffixResult::SVIncompatible) {
+  Diag(CurPtr, diag::err_cxx1z_string_view_literal)
+<< FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
+} else {
+  Diag(CurPtr, getLangOpts().MSVCCompat
+   ? diag::ext_ms_reserved_user_defined_literal
+   : diag::ext_reserved_user_defined_literal)
+<< FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
+  

[PATCH] D26830: [libcxx] Add string_view literals

2016-11-18 Thread Anton Bikineev via cfe-commits
AntonBikineev marked an inline comment as done.
AntonBikineev added inline comments.



Comment at: include/string_view:749
 
+inline namespace literals
+{

EricWF wrote:
> AntonBikineev wrote:
> > EricWF wrote:
> > > If this is new to C++17 then the new declarations should be guarded by 
> > > `#if _LIBCPP_VERSION > 14`.
> > Eric, I was thinking about it, but the fact that the whole string_view code 
> > is not guarded by _LIBCPP_VERSION > 14 (I guess it's because it can be 
> > compiled with lower Standards just fine) stopped me from doing that. I'm 
> > still not sure though.
> Understandable. The decision to backport most of `string_view` was 
> intentional. 
> 
> However we shouldn't backport these, since the literal suffix is only 
> supported by the compiler in C++17.
Agreed



https://reviews.llvm.org/D26830



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26830: [libcxx] Add string_view literals

2016-11-18 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 78498.

https://reviews.llvm.org/D26830

Files:
  include/string_view
  test/std/strings/string.view/string.view.literals/literal.pass.cpp
  test/std/strings/string.view/string.view.literals/literal1.fail.cpp
  test/std/strings/string.view/string.view.literals/literal1.pass.cpp
  test/std/strings/string.view/string.view.literals/literal2.fail.cpp
  test/std/strings/string.view/string.view.literals/literal2.pass.cpp
  test/std/strings/string.view/string.view.literals/literal3.pass.cpp

Index: test/std/strings/string.view/string.view.literals/literal3.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal3.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std;
+
+string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal2.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal2.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std::literals::string_view_literals;
+
+std::string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal2.fail.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal2.fail.cpp
@@ -0,0 +1,19 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+std::string_view foo  =   ""sv;  // should fail w/conversion operator not found
+}
Index: test/std/strings/string.view/string.view.literals/literal1.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal1.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std::literals;
+
+std::string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal1.fail.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal1.fail.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using std::string_view;
+
+string_view foo  =   ""sv;  // should fail w/conversion operator not found
+}
Index: test/std/strings/string.view/string.view.literals/literal.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal.pass.cpp
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and 

[PATCH] D26830: [libcxx] Add string_view literals

2016-11-18 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 78497.

https://reviews.llvm.org/D26830

Files:
  include/string_view
  test/std/strings/string.view/string.view.literals/literal.pass.cpp
  test/std/strings/string.view/string.view.literals/literal1.fail.cpp
  test/std/strings/string.view/string.view.literals/literal1.pass.cpp
  test/std/strings/string.view/string.view.literals/literal2.fail.cpp
  test/std/strings/string.view/string.view.literals/literal2.pass.cpp
  test/std/strings/string.view/string.view.literals/literal3.pass.cpp

Index: test/std/strings/string.view/string.view.literals/literal3.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal3.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std;
+
+string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal2.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal2.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std::literals::string_view_literals;
+
+std::string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal2.fail.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal2.fail.cpp
@@ -0,0 +1,19 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+std::string_view foo  =   ""sv;  // should fail w/conversion operator not found
+}
Index: test/std/strings/string.view/string.view.literals/literal1.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal1.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std::literals;
+
+std::string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal1.fail.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal1.fail.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using std::string_view;
+
+string_view foo  =   ""sv;  // should fail w/conversion operator not found
+}
Index: test/std/strings/string.view/string.view.literals/literal.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal.pass.cpp
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and 

[PATCH] D26830: [libcxx] Add string_view literals

2016-11-18 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 78493.
AntonBikineev marked an inline comment as done.

https://reviews.llvm.org/D26830

Files:
  include/string_view
  test/std/strings/string.view/string.view.literals/literal.pass.cpp
  test/std/strings/string.view/string.view.literals/literal1.fail.cpp
  test/std/strings/string.view/string.view.literals/literal1.pass.cpp
  test/std/strings/string.view/string.view.literals/literal2.fail.cpp
  test/std/strings/string.view/string.view.literals/literal2.pass.cpp
  test/std/strings/string.view/string.view.literals/literal3.pass.cpp

Index: test/std/strings/string.view/string.view.literals/literal3.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal3.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std;
+
+string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal2.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal2.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std::literals::string_view_literals;
+
+std::string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal2.fail.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal2.fail.cpp
@@ -0,0 +1,19 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+std::string_view foo  =   ""sv;  // should fail w/conversion operator not found
+}
Index: test/std/strings/string.view/string.view.literals/literal1.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal1.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std::literals;
+
+std::string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal1.fail.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal1.fail.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using std::string_view;
+
+string_view foo  =   ""sv;  // should fail w/conversion operator not found
+}
Index: test/std/strings/string.view/string.view.literals/literal.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal.pass.cpp
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//

[PATCH] D26830: [libcxx] Add string_view literals

2016-11-18 Thread Anton Bikineev via cfe-commits
AntonBikineev added inline comments.



Comment at: include/string_view:749
 
+inline namespace literals
+{

EricWF wrote:
> If this is new to C++17 then the new declarations should be guarded by `#if 
> _LIBCPP_VERSION > 14`.
Eric, I was thinking about it, but the fact that the whole string_view code is 
not guarded by _LIBCPP_VERSION > 14 (I guess it's because it can be compiled 
with lower Standards just fine) stopped me from doing that. I'm still not sure 
though.


https://reviews.llvm.org/D26830



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26829: [clang] Allow lexer to handle string_view literals

2016-11-18 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 78490.

https://reviews.llvm.org/D26829

Files:
  include/clang/Basic/DiagnosticLexKinds.td
  lib/Lex/Lexer.cpp


Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -1713,6 +1713,13 @@
  getLangOpts());
 if (!isIdentifierBody(Next)) {
   // End of suffix. Check whether this is on the whitelist.
+  if (Chars == 2 && Buffer[0] == 's' && Buffer[1] == 'v') {
+IsUDSuffix = true;
+if (!getLangOpts().CPlusPlus1z)
+  Diag(CurPtr, diag::warn_cxx1z_string_view_literal)
+<< FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
+break;
+  }
   IsUDSuffix = (Chars == 1 && Buffer[0] == 's') ||
NumericLiteralParser::isValidUDSuffix(
getLangOpts(), StringRef(Buffer, Chars));
Index: include/clang/Basic/DiagnosticLexKinds.td
===
--- include/clang/Basic/DiagnosticLexKinds.td
+++ include/clang/Basic/DiagnosticLexKinds.td
@@ -186,6 +186,8 @@
   "hexadecimal floating literals are incompatible with "
   "C++ standards before C++1z">,
   InGroup, DefaultIgnore;
+def warn_cxx1z_string_view_literal : Warning<
+  "string_view literals are a C++1z feature">, InGroup;
 def ext_binary_literal : Extension<
   "binary integer literals are a GNU extension">, InGroup;
 def ext_binary_literal_cxx14 : Extension<


Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -1713,6 +1713,13 @@
  getLangOpts());
 if (!isIdentifierBody(Next)) {
   // End of suffix. Check whether this is on the whitelist.
+  if (Chars == 2 && Buffer[0] == 's' && Buffer[1] == 'v') {
+IsUDSuffix = true;
+if (!getLangOpts().CPlusPlus1z)
+  Diag(CurPtr, diag::warn_cxx1z_string_view_literal)
+<< FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
+break;
+  }
   IsUDSuffix = (Chars == 1 && Buffer[0] == 's') ||
NumericLiteralParser::isValidUDSuffix(
getLangOpts(), StringRef(Buffer, Chars));
Index: include/clang/Basic/DiagnosticLexKinds.td
===
--- include/clang/Basic/DiagnosticLexKinds.td
+++ include/clang/Basic/DiagnosticLexKinds.td
@@ -186,6 +186,8 @@
   "hexadecimal floating literals are incompatible with "
   "C++ standards before C++1z">,
   InGroup, DefaultIgnore;
+def warn_cxx1z_string_view_literal : Warning<
+  "string_view literals are a C++1z feature">, InGroup;
 def ext_binary_literal : Extension<
   "binary integer literals are a GNU extension">, InGroup;
 def ext_binary_literal_cxx14 : Extension<
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26830: [libcxx] Add string_view literals

2016-11-17 Thread Anton Bikineev via cfe-commits
AntonBikineev created this revision.
AntonBikineev added reviewers: mclow.lists, rsmith, cfe-commits.
Herald added a reviewer: EricWF.

https://reviews.llvm.org/D26830

Files:
  include/string_view
  test/std/strings/string.view/string.view.literals/literal.pass.cpp
  test/std/strings/string.view/string.view.literals/literal1.fail.cpp
  test/std/strings/string.view/string.view.literals/literal1.pass.cpp
  test/std/strings/string.view/string.view.literals/literal2.fail.cpp
  test/std/strings/string.view/string.view.literals/literal2.pass.cpp
  test/std/strings/string.view/string.view.literals/literal3.pass.cpp

Index: test/std/strings/string.view/string.view.literals/literal3.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal3.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std;
+
+string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal2.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal2.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std::literals::string_view_literals;
+
+std::string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal2.fail.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal2.fail.cpp
@@ -0,0 +1,19 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+std::string_view foo  =   ""sv;  // should fail w/conversion operator not found
+}
Index: test/std/strings/string.view/string.view.literals/literal1.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal1.pass.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using namespace std::literals;
+
+std::string_view foo  =   ""sv;
+}
Index: test/std/strings/string.view/string.view.literals/literal1.fail.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal1.fail.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+#include 
+#include 
+
+int main()
+{
+using std::string_view;
+
+string_view foo  =   ""sv;  // should fail w/conversion operator not found
+}
Index: test/std/strings/string.view/string.view.literals/literal.pass.cpp
===
--- /dev/null
+++ test/std/strings/string.view/string.view.literals/literal.pass.cpp
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+//===--===//
+//
+// 

[PATCH] D26829: [clang] Allow lexer to handle string_view literals

2016-11-17 Thread Anton Bikineev via cfe-commits
AntonBikineev created this revision.
AntonBikineev added reviewers: mclow.lists, rsmith, cfe-commits.

https://reviews.llvm.org/D26829

Files:
  lib/Lex/Lexer.cpp


Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -1713,6 +1713,11 @@
  getLangOpts());
 if (!isIdentifierBody(Next)) {
   // End of suffix. Check whether this is on the whitelist.
+  if (getLangOpts().CPlusPlus1z && Chars == 2 && 
+  Buffer[0] == 's' && Buffer[1] == 'v') {
+IsUDSuffix = true;
+break;
+  }
   IsUDSuffix = (Chars == 1 && Buffer[0] == 's') ||
NumericLiteralParser::isValidUDSuffix(
getLangOpts(), StringRef(Buffer, Chars));


Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -1713,6 +1713,11 @@
  getLangOpts());
 if (!isIdentifierBody(Next)) {
   // End of suffix. Check whether this is on the whitelist.
+  if (getLangOpts().CPlusPlus1z && Chars == 2 && 
+  Buffer[0] == 's' && Buffer[1] == 'v') {
+IsUDSuffix = true;
+break;
+  }
   IsUDSuffix = (Chars == 1 && Buffer[0] == 's') ||
NumericLiteralParser::isValidUDSuffix(
getLangOpts(), StringRef(Buffer, Chars));
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21834: Implementing 'If statement with Initializer'

2016-07-11 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 63475.
AntonBikineev added a comment.

Moved stars to the right side of declarations


http://reviews.llvm.org/D21834

Files:
  include/clang/AST/Stmt.h
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/AST/ASTImporter.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Stmt.cpp
  lib/Analysis/BodyFarm.cpp
  lib/Analysis/CFG.cpp
  lib/CodeGen/CGStmt.cpp
  lib/Sema/JumpDiagnostics.cpp
  lib/Sema/SemaStmt.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  test/CodeGenCXX/cxx1z-init-statement.cpp
  test/PCH/cxx1z-init-statement.cpp
  test/PCH/cxx1z-init-statement.h
  test/Parser/cxx1z-init-statement.cpp
  test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
  test/SemaCXX/cxx1z-init-statement.cpp

Index: test/SemaCXX/cxx1z-init-statement.cpp
===
--- test/SemaCXX/cxx1z-init-statement.cpp
+++ test/SemaCXX/cxx1z-init-statement.cpp
@@ -0,0 +1,91 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+void testIf() {
+  int x = 0;
+  if (x; x) ++x;
+  if (int t = 0; t) ++t; else --t;
+
+  if (int x, y = 0; y) // expected-note 2 {{previous definition is here}}
+int x = 0; // expected-error {{redefinition of 'x'}}
+  else
+int x = 0; // expected-error {{redefinition of 'x'}}
+
+  if (x; int a = 0) ++a;
+  if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} expected-warning {{unused}}
+int a = 0; // expected-error {{redefinition of 'a'}}
+  else
+int a = 0; // expected-error {{redefinition of 'a'}}
+
+  if (int b = 0; b)
+;
+  b = 2; // expected-error {{use of undeclared identifier}}
+}
+
+void testSwitch() {
+  int x = 0;
+  switch (x; x) {
+case 1:
+  ++x;
+  }
+
+  switch (int x, y = 0; y) {
+case 1:
+  ++x;
+default:
+  ++y;
+  }
+
+  switch (int x, y = 0; y) { // expected-note 2 {{previous definition is here}}
+case 0:
+  int x = 0; // expected-error {{redefinition of 'x'}}
+case 1:
+  int y = 0; // expected-error {{redefinition of 'y'}}
+  };
+
+  switch (x; int a = 0) {
+case 0:
+  ++a;
+  }
+
+  switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} expected-warning {{unused}}
+case 0:
+  int a = 0; // expected-error {{redefinition of 'a'}} // expected-note {{previous definition is here}}
+case 1:
+  int a = 0; // expected-error {{redefinition of 'a'}}
+  }
+
+  switch (int b = 0; b) {
+case 0:
+  break;
+  }
+  b = 2; // expected-error {{use of undeclared identifier}}
+}
+
+constexpr bool constexpr_if_init(int n) {
+  if (int a = n; ++a > 0)
+return true;
+  else
+return false;
+}
+
+constexpr int constexpr_switch_init(int n) {
+  switch (int p = n + 2; p) {
+case 0:
+  return 0;
+case 1:
+  return 1;
+default:
+  return -1;
+  }
+}
+
+void test_constexpr_init_stmt() {
+  constexpr bool a = constexpr_if_init(-2);
+  static_assert(!a, "");
+  static_assert(constexpr_if_init(1), "");
+
+  constexpr int b = constexpr_switch_init(-1);
+  static_assert(b == 1, "");
+  static_assert(constexpr_switch_init(-2) == 0, "");
+  static_assert(constexpr_switch_init(-5) == -1, "");
+}
Index: test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
===
--- test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
+++ test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -std=c++1z -verify -Wuninitialized %s
+
+void testIf() {
+  if (bool b; b) // expected-warning {{uninitialized}} expected-note {{to silence}}
+;
+  if (int a, b = 2; a) // expected-warning {{uninitialized}} expected-note {{to silence}}
+;
+  int a;
+  if (a = 0; a) {} // OK
+}
+
+void testSwitch() {
+  switch (bool b; b) { // expected-warning {{uninitialized}} expected-warning {{boolean value}} expected-note {{to silence}}
+case 0:
+  break;
+  }
+  switch (int a, b = 7; a) { // expected-warning {{uninitialized}} expected-note {{to silence}}
+case 0:
+  break;
+  }
+  int c;
+  switch (c = 0; c) { // OK
+case 0:
+  break;
+  }
+}
Index: test/Parser/cxx1z-init-statement.cpp
===
--- test/Parser/cxx1z-init-statement.cpp
+++ test/Parser/cxx1z-init-statement.cpp
@@ -4,18 +4,18 @@
 typedef int T;
 int f() {
   // init-statement declarations
-  if (T n = 0; n != 0) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T(f()); f()) {} // expected-error {{not yet supported}}
-  if (T(f()), g, h; f()) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T f(), g, h; f()) {} // expected-error {{not yet supported}}
-  if (T(n) = 0; n) {} // expected-error {{not yet supported}}
+  if (T n = 0; n != 0) {}
+  if (T f(); f()) {}
+  if (T(f()); f()) 

Re: [PATCH] D21834: Implementing 'If statement with Initializer'

2016-07-11 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 63474.

http://reviews.llvm.org/D21834

Files:
  include/clang/AST/Stmt.h
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/AST/ASTImporter.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Stmt.cpp
  lib/Analysis/BodyFarm.cpp
  lib/Analysis/CFG.cpp
  lib/CodeGen/CGStmt.cpp
  lib/Sema/JumpDiagnostics.cpp
  lib/Sema/SemaStmt.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  test/CodeGenCXX/cxx1z-init-statement.cpp
  test/PCH/cxx1z-init-statement.cpp
  test/PCH/cxx1z-init-statement.h
  test/Parser/cxx1z-init-statement.cpp
  test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
  test/SemaCXX/cxx1z-init-statement.cpp

Index: test/SemaCXX/cxx1z-init-statement.cpp
===
--- test/SemaCXX/cxx1z-init-statement.cpp
+++ test/SemaCXX/cxx1z-init-statement.cpp
@@ -0,0 +1,91 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+void testIf() {
+  int x = 0;
+  if (x; x) ++x;
+  if (int t = 0; t) ++t; else --t;
+
+  if (int x, y = 0; y) // expected-note 2 {{previous definition is here}}
+int x = 0; // expected-error {{redefinition of 'x'}}
+  else
+int x = 0; // expected-error {{redefinition of 'x'}}
+
+  if (x; int a = 0) ++a;
+  if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} expected-warning {{unused}}
+int a = 0; // expected-error {{redefinition of 'a'}}
+  else
+int a = 0; // expected-error {{redefinition of 'a'}}
+
+  if (int b = 0; b)
+;
+  b = 2; // expected-error {{use of undeclared identifier}}
+}
+
+void testSwitch() {
+  int x = 0;
+  switch (x; x) {
+case 1:
+  ++x;
+  }
+
+  switch (int x, y = 0; y) {
+case 1:
+  ++x;
+default:
+  ++y;
+  }
+
+  switch (int x, y = 0; y) { // expected-note 2 {{previous definition is here}}
+case 0:
+  int x = 0; // expected-error {{redefinition of 'x'}}
+case 1:
+  int y = 0; // expected-error {{redefinition of 'y'}}
+  };
+
+  switch (x; int a = 0) {
+case 0:
+  ++a;
+  }
+
+  switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} expected-warning {{unused}}
+case 0:
+  int a = 0; // expected-error {{redefinition of 'a'}} // expected-note {{previous definition is here}}
+case 1:
+  int a = 0; // expected-error {{redefinition of 'a'}}
+  }
+
+  switch (int b = 0; b) {
+case 0:
+  break;
+  }
+  b = 2; // expected-error {{use of undeclared identifier}}
+}
+
+constexpr bool constexpr_if_init(int n) {
+  if (int a = n; ++a > 0)
+return true;
+  else
+return false;
+}
+
+constexpr int constexpr_switch_init(int n) {
+  switch (int p = n + 2; p) {
+case 0:
+  return 0;
+case 1:
+  return 1;
+default:
+  return -1;
+  }
+}
+
+void test_constexpr_init_stmt() {
+  constexpr bool a = constexpr_if_init(-2);
+  static_assert(!a, "");
+  static_assert(constexpr_if_init(1), "");
+
+  constexpr int b = constexpr_switch_init(-1);
+  static_assert(b == 1, "");
+  static_assert(constexpr_switch_init(-2) == 0, "");
+  static_assert(constexpr_switch_init(-5) == -1, "");
+}
Index: test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
===
--- test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
+++ test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -std=c++1z -verify -Wuninitialized %s
+
+void testIf() {
+  if (bool b; b) // expected-warning {{uninitialized}} expected-note {{to silence}}
+;
+  if (int a, b = 2; a) // expected-warning {{uninitialized}} expected-note {{to silence}}
+;
+  int a;
+  if (a = 0; a) {} // OK
+}
+
+void testSwitch() {
+  switch (bool b; b) { // expected-warning {{uninitialized}} expected-warning {{boolean value}} expected-note {{to silence}}
+case 0:
+  break;
+  }
+  switch (int a, b = 7; a) { // expected-warning {{uninitialized}} expected-note {{to silence}}
+case 0:
+  break;
+  }
+  int c;
+  switch (c = 0; c) { // OK
+case 0:
+  break;
+  }
+}
Index: test/Parser/cxx1z-init-statement.cpp
===
--- test/Parser/cxx1z-init-statement.cpp
+++ test/Parser/cxx1z-init-statement.cpp
@@ -4,18 +4,18 @@
 typedef int T;
 int f() {
   // init-statement declarations
-  if (T n = 0; n != 0) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T(f()); f()) {} // expected-error {{not yet supported}}
-  if (T(f()), g, h; f()) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T f(), g, h; f()) {} // expected-error {{not yet supported}}
-  if (T(n) = 0; n) {} // expected-error {{not yet supported}}
+  if (T n = 0; n != 0) {}
+  if (T f(); f()) {}
+  if (T(f()); f()) {}
+  if (T(f()), g, h; f()) {}
+  if (T f(); f()) {}
+  if (T f(), g, h; f()) 

Re: [PATCH] D21834: Implementing 'If statement with Initializer'

2016-07-11 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 63473.
AntonBikineev added a comment.

removed a leftover from parser/cxx1z-init-stmt.cpp test


http://reviews.llvm.org/D21834

Files:
  include/clang/AST/Stmt.h
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/AST/ASTImporter.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Stmt.cpp
  lib/Analysis/BodyFarm.cpp
  lib/Analysis/CFG.cpp
  lib/CodeGen/CGStmt.cpp
  lib/Sema/JumpDiagnostics.cpp
  lib/Sema/SemaStmt.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  test/CodeGenCXX/cxx1z-init-statement.cpp
  test/PCH/cxx1z-init-statement.cpp
  test/PCH/cxx1z-init-statement.h
  test/Parser/cxx1z-init-statement.cpp
  test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
  test/SemaCXX/cxx1z-init-statement.cpp

Index: test/SemaCXX/cxx1z-init-statement.cpp
===
--- test/SemaCXX/cxx1z-init-statement.cpp
+++ test/SemaCXX/cxx1z-init-statement.cpp
@@ -0,0 +1,91 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+void testIf() {
+  int x = 0;
+  if (x; x) ++x;
+  if (int t = 0; t) ++t; else --t;
+
+  if (int x, y = 0; y) // expected-note 2 {{previous definition is here}}
+int x = 0; // expected-error {{redefinition of 'x'}}
+  else
+int x = 0; // expected-error {{redefinition of 'x'}}
+
+  if (x; int a = 0) ++a;
+  if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} expected-warning {{unused}}
+int a = 0; // expected-error {{redefinition of 'a'}}
+  else
+int a = 0; // expected-error {{redefinition of 'a'}}
+
+  if (int b = 0; b)
+;
+  b = 2; // expected-error {{use of undeclared identifier}}
+}
+
+void testSwitch() {
+  int x = 0;
+  switch (x; x) {
+case 1:
+  ++x;
+  }
+
+  switch (int x, y = 0; y) {
+case 1:
+  ++x;
+default:
+  ++y;
+  }
+
+  switch (int x, y = 0; y) { // expected-note 2 {{previous definition is here}}
+case 0:
+  int x = 0; // expected-error {{redefinition of 'x'}}
+case 1:
+  int y = 0; // expected-error {{redefinition of 'y'}}
+  };
+
+  switch (x; int a = 0) {
+case 0:
+  ++a;
+  }
+
+  switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} expected-warning {{unused}}
+case 0:
+  int a = 0; // expected-error {{redefinition of 'a'}} // expected-note {{previous definition is here}}
+case 1:
+  int a = 0; // expected-error {{redefinition of 'a'}}
+  }
+
+  switch (int b = 0; b) {
+case 0:
+  break;
+  }
+  b = 2; // expected-error {{use of undeclared identifier}}
+}
+
+constexpr bool constexpr_if_init(int n) {
+  if (int a = n; ++a > 0)
+return true;
+  else
+return false;
+}
+
+constexpr int constexpr_switch_init(int n) {
+  switch (int p = n + 2; p) {
+case 0:
+  return 0;
+case 1:
+  return 1;
+default:
+  return -1;
+  }
+}
+
+void test_constexpr_init_stmt() {
+  constexpr bool a = constexpr_if_init(-2);
+  static_assert(!a, "");
+  static_assert(constexpr_if_init(1), "");
+
+  constexpr int b = constexpr_switch_init(-1);
+  static_assert(b == 1, "");
+  static_assert(constexpr_switch_init(-2) == 0, "");
+  static_assert(constexpr_switch_init(-5) == -1, "");
+}
Index: test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
===
--- test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
+++ test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -std=c++1z -verify -Wuninitialized %s
+
+void testIf() {
+  if (bool b; b) // expected-warning {{uninitialized}} expected-note {{to silence}}
+;
+  if (int a, b = 2; a) // expected-warning {{uninitialized}} expected-note {{to silence}}
+;
+  int a;
+  if (a = 0; a) {} // OK
+}
+
+void testSwitch() {
+  switch (bool b; b) { // expected-warning {{uninitialized}} expected-warning {{boolean value}} expected-note {{to silence}}
+case 0:
+  break;
+  }
+  switch (int a, b = 7; a) { // expected-warning {{uninitialized}} expected-note {{to silence}}
+case 0:
+  break;
+  }
+  int c;
+  switch (c = 0; c) { // OK
+case 0:
+  break;
+  }
+}
Index: test/Parser/cxx1z-init-statement.cpp
===
--- test/Parser/cxx1z-init-statement.cpp
+++ test/Parser/cxx1z-init-statement.cpp
@@ -4,18 +4,18 @@
 typedef int T;
 int f() {
   // init-statement declarations
-  if (T n = 0; n != 0) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T(f()); f()) {} // expected-error {{not yet supported}}
-  if (T(f()), g, h; f()) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T f(), g, h; f()) {} // expected-error {{not yet supported}}
+  if (T n = 0; n != 0) {}
+  if (T f(); f()) {}
+  if (T(f()); f()) {}
+  if (T(f()), g, h; f()) {}
+  if (T f(); f()) {}

Re: [PATCH] D21834: Implementing 'If statement with Initializer'

2016-07-11 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 63472.

http://reviews.llvm.org/D21834

Files:
  include/clang/AST/Stmt.h
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/AST/ASTImporter.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Stmt.cpp
  lib/Analysis/BodyFarm.cpp
  lib/Analysis/CFG.cpp
  lib/CodeGen/CGStmt.cpp
  lib/Sema/JumpDiagnostics.cpp
  lib/Sema/SemaStmt.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  test/CodeGenCXX/cxx1z-init-statement.cpp
  test/PCH/cxx1z-init-statement.cpp
  test/PCH/cxx1z-init-statement.h
  test/Parser/cxx1z-init-statement.cpp
  test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
  test/SemaCXX/cxx1z-init-statement.cpp

Index: test/SemaCXX/cxx1z-init-statement.cpp
===
--- test/SemaCXX/cxx1z-init-statement.cpp
+++ test/SemaCXX/cxx1z-init-statement.cpp
@@ -0,0 +1,91 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+void testIf() {
+  int x = 0;
+  if (x; x) ++x;
+  if (int t = 0; t) ++t; else --t;
+
+  if (int x, y = 0; y) // expected-note 2 {{previous definition is here}}
+int x = 0; // expected-error {{redefinition of 'x'}}
+  else
+int x = 0; // expected-error {{redefinition of 'x'}}
+
+  if (x; int a = 0) ++a;
+  if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} expected-warning {{unused}}
+int a = 0; // expected-error {{redefinition of 'a'}}
+  else
+int a = 0; // expected-error {{redefinition of 'a'}}
+
+  if (int b = 0; b)
+;
+  b = 2; // expected-error {{use of undeclared identifier}}
+}
+
+void testSwitch() {
+  int x = 0;
+  switch (x; x) {
+case 1:
+  ++x;
+  }
+
+  switch (int x, y = 0; y) {
+case 1:
+  ++x;
+default:
+  ++y;
+  }
+
+  switch (int x, y = 0; y) { // expected-note 2 {{previous definition is here}}
+case 0:
+  int x = 0; // expected-error {{redefinition of 'x'}}
+case 1:
+  int y = 0; // expected-error {{redefinition of 'y'}}
+  };
+
+  switch (x; int a = 0) {
+case 0:
+  ++a;
+  }
+
+  switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} expected-warning {{unused}}
+case 0:
+  int a = 0; // expected-error {{redefinition of 'a'}} // expected-note {{previous definition is here}}
+case 1:
+  int a = 0; // expected-error {{redefinition of 'a'}}
+  }
+
+  switch (int b = 0; b) {
+case 0:
+  break;
+  }
+  b = 2; // expected-error {{use of undeclared identifier}}
+}
+
+constexpr bool constexpr_if_init(int n) {
+  if (int a = n; ++a > 0)
+return true;
+  else
+return false;
+}
+
+constexpr int constexpr_switch_init(int n) {
+  switch (int p = n + 2; p) {
+case 0:
+  return 0;
+case 1:
+  return 1;
+default:
+  return -1;
+  }
+}
+
+void test_constexpr_init_stmt() {
+  constexpr bool a = constexpr_if_init(-2);
+  static_assert(!a, "");
+  static_assert(constexpr_if_init(1), "");
+
+  constexpr int b = constexpr_switch_init(-1);
+  static_assert(b == 1, "");
+  static_assert(constexpr_switch_init(-2) == 0, "");
+  static_assert(constexpr_switch_init(-5) == -1, "");
+}
Index: test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
===
--- test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
+++ test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -std=c++1z -verify -Wuninitialized %s
+
+void testIf() {
+  if (bool b; b) // expected-warning {{uninitialized}} expected-note {{to silence}}
+;
+  if (int a, b = 2; a) // expected-warning {{uninitialized}} expected-note {{to silence}}
+;
+  int a;
+  if (a = 0; a) {} // OK
+}
+
+void testSwitch() {
+  switch (bool b; b) { // expected-warning {{uninitialized}} expected-warning {{boolean value}} expected-note {{to silence}}
+case 0:
+  break;
+  }
+  switch (int a, b = 7; a) { // expected-warning {{uninitialized}} expected-note {{to silence}}
+case 0:
+  break;
+  }
+  int c;
+  switch (c = 0; c) { // OK
+case 0:
+  break;
+  }
+}
Index: test/Parser/cxx1z-init-statement.cpp
===
--- test/Parser/cxx1z-init-statement.cpp
+++ test/Parser/cxx1z-init-statement.cpp
@@ -4,18 +4,18 @@
 typedef int T;
 int f() {
   // init-statement declarations
-  if (T n = 0; n != 0) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T(f()); f()) {} // expected-error {{not yet supported}}
-  if (T(f()), g, h; f()) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T f(), g, h; f()) {} // expected-error {{not yet supported}}
+  if (T n = 0; n != 0) {}
+  if (T f(); f()) {}
+  if (T(f()); f()) {}
+  if (T(f()), g, h; f()) {}
+  if (T f(); f()) {}
+  if (T f(), g, h; f()) {}
   if (T(n) = 0; n) {} // expected-error {{not yet 

Re: [PATCH] D21834: Implementing 'If statement with Initializer'

2016-07-11 Thread Anton Bikineev via cfe-commits
AntonBikineev updated the summary for this revision.
AntonBikineev updated this revision to Diff 63471.
AntonBikineev added a comment.

@rsmith,
Richard, again, thank you for guiding. I've addressed your comments.


http://reviews.llvm.org/D21834

Files:
  include/clang/AST/Stmt.h
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/AST/ASTImporter.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Stmt.cpp
  lib/Analysis/BodyFarm.cpp
  lib/Analysis/CFG.cpp
  lib/CodeGen/CGStmt.cpp
  lib/Sema/JumpDiagnostics.cpp
  lib/Sema/SemaStmt.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  test/CodeGenCXX/cxx1z-init-statement.cpp
  test/PCH/cxx1z-init-statement.cpp
  test/PCH/cxx1z-init-statement.h
  test/Parser/cxx1z-init-statement.cpp
  test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
  test/SemaCXX/cxx1z-init-statement.cpp

Index: test/SemaCXX/cxx1z-init-statement.cpp
===
--- test/SemaCXX/cxx1z-init-statement.cpp
+++ test/SemaCXX/cxx1z-init-statement.cpp
@@ -0,0 +1,91 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+void testIf() {
+  int x = 0;
+  if (x; x) ++x;
+  if (int t = 0; t) ++t; else --t;
+
+  if (int x, y = 0; y) // expected-note 2 {{previous definition is here}}
+int x = 0; // expected-error {{redefinition of 'x'}}
+  else
+int x = 0; // expected-error {{redefinition of 'x'}}
+
+  if (x; int a = 0) ++a;
+  if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} expected-warning {{unused}}
+int a = 0; // expected-error {{redefinition of 'a'}}
+  else
+int a = 0; // expected-error {{redefinition of 'a'}}
+
+  if (int b = 0; b)
+;
+  b = 2; // expected-error {{use of undeclared identifier}}
+}
+
+void testSwitch() {
+  int x = 0;
+  switch (x; x) {
+case 1:
+  ++x;
+  }
+
+  switch (int x, y = 0; y) {
+case 1:
+  ++x;
+default:
+  ++y;
+  }
+
+  switch (int x, y = 0; y) { // expected-note 2 {{previous definition is here}}
+case 0:
+  int x = 0; // expected-error {{redefinition of 'x'}}
+case 1:
+  int y = 0; // expected-error {{redefinition of 'y'}}
+  };
+
+  switch (x; int a = 0) {
+case 0:
+  ++a;
+  }
+
+  switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} expected-warning {{unused}}
+case 0:
+  int a = 0; // expected-error {{redefinition of 'a'}} // expected-note {{previous definition is here}}
+case 1:
+  int a = 0; // expected-error {{redefinition of 'a'}}
+  }
+
+  switch (int b = 0; b) {
+case 0:
+  break;
+  }
+  b = 2; // expected-error {{use of undeclared identifier}}
+}
+
+constexpr bool constexpr_if_init(int n) {
+  if (int a = n; ++a > 0)
+return true;
+  else
+return false;
+}
+
+constexpr int constexpr_switch_init(int n) {
+  switch (int p = n + 2; p) {
+case 0:
+  return 0;
+case 1:
+  return 1;
+default:
+  return -1;
+  }
+}
+
+void test_constexpr_init_stmt() {
+  constexpr bool a = constexpr_if_init(-2);
+  static_assert(!a, "");
+  static_assert(constexpr_if_init(1), "");
+
+  constexpr int b = constexpr_switch_init(-1);
+  static_assert(b == 1, "");
+  static_assert(constexpr_switch_init(-2) == 0, "");
+  static_assert(constexpr_switch_init(-5) == -1, "");
+}
Index: test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
===
--- test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
+++ test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -std=c++1z -verify -Wuninitialized %s
+
+void testIf() {
+  if (bool b; b) // expected-warning {{uninitialized}} expected-note {{to silence}}
+;
+  if (int a, b = 2; a) // expected-warning {{uninitialized}} expected-note {{to silence}}
+;
+  int a;
+  if (a = 0; a) {} // OK
+}
+
+void testSwitch() {
+  switch (bool b; b) { // expected-warning {{uninitialized}} expected-warning {{boolean value}} expected-note {{to silence}}
+case 0:
+  break;
+  }
+  switch (int a, b = 7; a) { // expected-warning {{uninitialized}} expected-note {{to silence}}
+case 0:
+  break;
+  }
+  int c;
+  switch (c = 0; c) { // OK
+case 0:
+  break;
+  }
+}
Index: test/Parser/cxx1z-init-statement.cpp
===
--- test/Parser/cxx1z-init-statement.cpp
+++ test/Parser/cxx1z-init-statement.cpp
@@ -4,18 +4,18 @@
 typedef int T;
 int f() {
   // init-statement declarations
-  if (T n = 0; n != 0) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T(f()); f()) {} // expected-error {{not yet supported}}
-  if (T(f()), g, h; f()) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T f(), g, h; f()) {} // expected-error {{not yet supported}}
+  if (T n = 0; n != 0) {}
+  if (T f(); f()) {}

Re: [PATCH] D21834: Implementing 'If statement with Initializer'

2016-07-07 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 63056.
AntonBikineev added a comment.

@rsmith,
I've added some tests for c++1z init statement. Please let me know if there is 
anything else I should add or change.


http://reviews.llvm.org/D21834

Files:
  include/clang/AST/Stmt.h
  include/clang/Sema/Sema.h
  lib/AST/ASTImporter.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Stmt.cpp
  lib/Analysis/BodyFarm.cpp
  lib/Analysis/CFG.cpp
  lib/CodeGen/CGStmt.cpp
  lib/Sema/JumpDiagnostics.cpp
  lib/Sema/SemaStmt.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  test/CodeGenCXX/cxx1z-init-statement.cpp
  test/PCH/cxx1z-init-statement.cpp
  test/PCH/cxx1z-init-statement.h
  test/Parser/cxx1z-init-statement.cpp
  test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
  test/SemaCXX/cxx1z-init-statement.cpp

Index: test/SemaCXX/cxx1z-init-statement.cpp
===
--- test/SemaCXX/cxx1z-init-statement.cpp
+++ test/SemaCXX/cxx1z-init-statement.cpp
@@ -0,0 +1,91 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+void testIf() {
+  int x = 0;
+  if (x; x) ++x;
+  if (int t = 0; t) ++t; else --t;
+
+  if (int x, y = 0; y) // expected-note 2 {{previous definition is here}}
+int x = 0; // expected-error {{redefinition of 'x'}}
+  else
+int x = 0; // expected-error {{redefinition of 'x'}}
+
+  if (x; int a = 0) ++a;
+  if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} expected-warning {{unused}}
+int a = 0; // expected-error {{redefinition of 'a'}}
+  else
+int a = 0; // expected-error {{redefinition of 'a'}}
+
+  if (int b = 0; b)
+;
+  b = 2; // expected-error {{use of undeclared identifier}}
+}
+
+void testSwitch() {
+  int x = 0;
+  switch (x; x) {
+case 1:
+  ++x;
+  }
+
+  switch (int x, y = 0; y) {
+case 1:
+  ++x;
+default:
+  ++y;
+  }
+
+  switch (int x, y = 0; y) { // expected-note 2 {{previous definition is here}}
+case 0:
+  int x = 0; // expected-error {{redefinition of 'x'}}
+case 1:
+  int y = 0; // expected-error {{redefinition of 'y'}}
+  };
+
+  switch (x; int a = 0) {
+case 0:
+  ++a;
+  }
+
+  switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} expected-warning {{unused}}
+case 0:
+  int a = 0; // expected-error {{redefinition of 'a'}} // expected-note {{previous definition is here}}
+case 1:
+  int a = 0; // expected-error {{redefinition of 'a'}}
+  }
+
+  switch (int b = 0; b) {
+case 0:
+  break;
+  }
+  b = 2; // expected-error {{use of undeclared identifier}}
+}
+
+constexpr bool constexpr_if_init(int n) {
+  if (int a = n; ++a > 0)
+return true;
+  else
+return false;
+}
+
+constexpr int constexpr_switch_init(int n) {
+  switch (int p = n + 2; p) {
+case 0:
+  return 0;
+case 1:
+  return 1;
+default:
+  return -1;
+  }
+}
+
+void test_constexpr_init_stmt() {
+  constexpr bool a = constexpr_if_init(-2);
+  static_assert(!a, "");
+  static_assert(constexpr_if_init(1), "");
+
+  constexpr int b = constexpr_switch_init(-1);
+  static_assert(b == 1, "");
+  static_assert(constexpr_switch_init(-2) == 0, "");
+  static_assert(constexpr_switch_init(-5) == -1, "");
+}
Index: test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
===
--- test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
+++ test/SemaCXX/cxx1z-init-statement-warn-unused.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -std=c++1z -verify -Wuninitialized %s
+
+void testIf() {
+  if (bool b; b) // expected-warning {{uninitialized}} expected-note {{to silence}}
+;
+  if (int a, b = 2; a) // expected-warning {{uninitialized}} expected-note {{to silence}}
+;
+}
+
+void testSwitch() {
+  switch (bool b; b) { // expected-warning {{uninitialized}} expected-warning {{boolean value}} expected-note {{to silence}}
+case 0:
+  break;
+  }
+  switch (int a, b = 7; a) { // expected-warning {{uninitialized}} expected-note {{to silence}}
+case 0:
+  break;
+  }
+}
Index: test/Parser/cxx1z-init-statement.cpp
===
--- test/Parser/cxx1z-init-statement.cpp
+++ test/Parser/cxx1z-init-statement.cpp
@@ -4,17 +4,17 @@
 typedef int T;
 int f() {
   // init-statement declarations
-  if (T n = 0; n != 0) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T(f()); f()) {} // expected-error {{not yet supported}}
-  if (T(f()), g, h; f()) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T f(), g, h; f()) {} // expected-error {{not yet supported}}
+  if (T n = 0; n != 0) {}
+  if (T f(); f()) {}
+  if (T(f()); f()) {}
+  if (T(f()), g, h; f()) {}
+  if (T f(); f()) {}
+  if (T f(), g, h; f()) {}
 
   // init-statement expressions
-  if (T{f()}; 

Re: [PATCH] D21834: Implementing 'If statement with Initializer'

2016-07-05 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 62790.
AntonBikineev added a comment.

@rsmith,
Thanks for the comments, I've addressed them (except for tests, they are to be 
added asap). I'm especially not sure about changes in CFG.cpp, could you verify 
please?


http://reviews.llvm.org/D21834

Files:
  include/clang/AST/Stmt.h
  include/clang/Sema/Sema.h
  lib/AST/ASTImporter.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Stmt.cpp
  lib/Analysis/BodyFarm.cpp
  lib/Analysis/CFG.cpp
  lib/CodeGen/CGStmt.cpp
  lib/Sema/JumpDiagnostics.cpp
  lib/Sema/SemaStmt.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  test/Parser/cxx1z-init-statement.cpp

Index: test/Parser/cxx1z-init-statement.cpp
===
--- test/Parser/cxx1z-init-statement.cpp
+++ test/Parser/cxx1z-init-statement.cpp
@@ -4,17 +4,17 @@
 typedef int T;
 int f() {
   // init-statement declarations
-  if (T n = 0; n != 0) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T(f()); f()) {} // expected-error {{not yet supported}}
-  if (T(f()), g, h; f()) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T f(), g, h; f()) {} // expected-error {{not yet supported}}
+  if (T n = 0; n != 0) {}
+  if (T f(); f()) {}
+  if (T(f()); f()) {}
+  if (T(f()), g, h; f()) {}
+  if (T f(); f()) {}
+  if (T f(), g, h; f()) {}
 
   // init-statement expressions
-  if (T{f()}; f()) {} // expected-error {{not yet supported}}
-  if (T{f()}, g, h; f()) {} // expected-error {{not yet supported}} expected-warning 2{{unused}}
-  if (T(f()), g, h + 1; f()) {} // expected-error {{not yet supported}} expected-warning 2{{unused}}
+  if (T{f()}; f()) {}
+  if (T{f()}, g, h; f()) {} // expected-warning 2{{unused}}
+  if (T(f()), g, h + 1; f()) {} // expected-warning 2{{unused}}
 
   // condition declarations
   if (T(n){g}) {}
@@ -32,10 +32,10 @@
   //if (T(n)(g)) {} // expected-err-FIXME {{not a function}}
 
   // Likewise for 'switch'
-  switch (int n; n) {} // expected-error {{not yet supported}}
-  switch (g; int g = 5) {} // expected-error {{not yet supported}}
+  switch (int n; n) {}
+  switch (g; int g = 5) {}
 
-  if (int a, b; int c = a) { // expected-error {{not yet supported}} expected-note 6{{previous}}
+  if (int a, b; int c = a) { // expected-note 6{{previous}}
 int a; // expected-error {{redefinition}}
 int b; // expected-error {{redefinition}}
 int c; // expected-error {{redefinition}}
@@ -44,4 +44,6 @@
 int b; // expected-error {{redefinition}}
 int c; // expected-error {{redefinition}}
   }
+
+  return 0;
 }
Index: lib/Serialization/ASTWriterStmt.cpp
===
--- lib/Serialization/ASTWriterStmt.cpp
+++ lib/Serialization/ASTWriterStmt.cpp
@@ -129,6 +129,7 @@
 void ASTStmtWriter::VisitIfStmt(IfStmt *S) {
   VisitStmt(S);
   Record.push_back(S->isConstexpr());
+  Record.AddStmt(S->getInit());
   Record.AddDeclRef(S->getConditionVariable());
   Record.AddStmt(S->getCond());
   Record.AddStmt(S->getThen());
@@ -140,6 +141,7 @@
 
 void ASTStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
   VisitStmt(S);
+  Record.AddStmt(S->getInit());
   Record.AddDeclRef(S->getConditionVariable());
   Record.AddStmt(S->getCond());
   Record.AddStmt(S->getBody());
Index: lib/Serialization/ASTReaderStmt.cpp
===
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -185,6 +185,7 @@
 void ASTStmtReader::VisitIfStmt(IfStmt *S) {
   VisitStmt(S);
   S->setConstexpr(Record[Idx++]);
+  S->setInit(Reader.ReadSubStmt());
   S->setConditionVariable(Reader.getContext(),
   ReadDeclAs(Record, Idx));
   S->setCond(Reader.ReadSubExpr());
@@ -196,6 +197,7 @@
 
 void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) {
   VisitStmt(S);
+  S->setInit(Reader.ReadSubStmt());
   S->setConditionVariable(Reader.getContext(),
   ReadDeclAs(Record, Idx));
   S->setCond(Reader.ReadSubExpr());
Index: lib/Sema/TreeTransform.h
===
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -1174,9 +1174,9 @@
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
   StmtResult RebuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
-   Sema::ConditionResult Cond, Stmt *Then,
+   Sema::ConditionResult Cond, Stmt *Init, Stmt *Then,
SourceLocation ElseLoc, Stmt *Else) {
-return getSema().ActOnIfStmt(IfLoc, IsConstexpr, nullptr, Cond, Then,
+return getSema().ActOnIfStmt(IfLoc, IsConstexpr, Init, Cond, Then,
  

Re: [PATCH] D21834: Implementing 'If statement with Initializer'

2016-06-29 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 62321.
AntonBikineev added a comment.

Test Parser/cxx1z-init-statement.cpp has been updated according to Sema changes


http://reviews.llvm.org/D21834

Files:
  include/clang/AST/Stmt.h
  include/clang/Sema/Sema.h
  lib/AST/ASTImporter.cpp
  lib/AST/Stmt.cpp
  lib/Analysis/BodyFarm.cpp
  lib/CodeGen/CGStmt.cpp
  lib/Sema/SemaStmt.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  test/Parser/cxx1z-init-statement.cpp

Index: test/Parser/cxx1z-init-statement.cpp
===
--- test/Parser/cxx1z-init-statement.cpp
+++ test/Parser/cxx1z-init-statement.cpp
@@ -4,17 +4,17 @@
 typedef int T;
 int f() {
   // init-statement declarations
-  if (T n = 0; n != 0) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T(f()); f()) {} // expected-error {{not yet supported}}
-  if (T(f()), g, h; f()) {} // expected-error {{not yet supported}}
-  if (T f(); f()) {} // expected-error {{not yet supported}}
-  if (T f(), g, h; f()) {} // expected-error {{not yet supported}}
+  if (T n = 0; n != 0) {}
+  if (T f(); f()) {}
+  if (T(f()); f()) {}
+  if (T(f()), g, h; f()) {}
+  if (T f(); f()) {}
+  if (T f(), g, h; f()) {}
 
   // init-statement expressions
-  if (T{f()}; f()) {} // expected-error {{not yet supported}}
-  if (T{f()}, g, h; f()) {} // expected-error {{not yet supported}} expected-warning 2{{unused}}
-  if (T(f()), g, h + 1; f()) {} // expected-error {{not yet supported}} expected-warning 2{{unused}}
+  if (T{f()}; f()) {}
+  if (T{f()}, g, h; f()) {} // expected-warning 2{{unused}}
+  if (T(f()), g, h + 1; f()) {} // expected-warning 2{{unused}}
 
   // condition declarations
   if (T(n){g}) {}
@@ -32,10 +32,10 @@
   //if (T(n)(g)) {} // expected-err-FIXME {{not a function}}
 
   // Likewise for 'switch'
-  switch (int n; n) {} // expected-error {{not yet supported}}
-  switch (g; int g = 5) {} // expected-error {{not yet supported}}
+  switch (int n; n) {}
+  switch (g; int g = 5) {}
 
-  if (int a, b; int c = a) { // expected-error {{not yet supported}} expected-note 6{{previous}}
+  if (int a, b; int c = a) { // expected-note 6{{previous}}
 int a; // expected-error {{redefinition}}
 int b; // expected-error {{redefinition}}
 int c; // expected-error {{redefinition}}
@@ -44,4 +44,6 @@
 int b; // expected-error {{redefinition}}
 int c; // expected-error {{redefinition}}
   }
+
+  return 0;
 }
Index: lib/Serialization/ASTWriterStmt.cpp
===
--- lib/Serialization/ASTWriterStmt.cpp
+++ lib/Serialization/ASTWriterStmt.cpp
@@ -129,6 +129,7 @@
 void ASTStmtWriter::VisitIfStmt(IfStmt *S) {
   VisitStmt(S);
   Record.push_back(S->isConstexpr());
+  Record.AddStmt(S->getInit());
   Record.AddDeclRef(S->getConditionVariable());
   Record.AddStmt(S->getCond());
   Record.AddStmt(S->getThen());
@@ -140,6 +141,7 @@
 
 void ASTStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
   VisitStmt(S);
+  Record.AddStmt(S->getInit());
   Record.AddDeclRef(S->getConditionVariable());
   Record.AddStmt(S->getCond());
   Record.AddStmt(S->getBody());
Index: lib/Serialization/ASTReaderStmt.cpp
===
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -185,6 +185,7 @@
 void ASTStmtReader::VisitIfStmt(IfStmt *S) {
   VisitStmt(S);
   S->setConstexpr(Record[Idx++]);
+  S->setInit(Reader.ReadSubStmt());
   S->setConditionVariable(Reader.getContext(),
   ReadDeclAs(Record, Idx));
   S->setCond(Reader.ReadSubExpr());
@@ -196,6 +197,7 @@
 
 void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) {
   VisitStmt(S);
+  S->setInit(Reader.ReadSubStmt());
   S->setConditionVariable(Reader.getContext(),
   ReadDeclAs(Record, Idx));
   S->setCond(Reader.ReadSubExpr());
Index: lib/Sema/TreeTransform.h
===
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -1174,9 +1174,9 @@
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
   StmtResult RebuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
-   Sema::ConditionResult Cond, Stmt *Then,
+   Sema::ConditionResult Cond, Stmt *Init, Stmt *Then,
SourceLocation ElseLoc, Stmt *Else) {
-return getSema().ActOnIfStmt(IfLoc, IsConstexpr, nullptr, Cond, Then,
+return getSema().ActOnIfStmt(IfLoc, IsConstexpr, Init, Cond, Then,
  ElseLoc, Else);
   }
 
@@ -1185,8 +1185,9 @@
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different 

Re: [PATCH] D21834: Implementing 'If statement with Initializer'

2016-06-29 Thread Anton Bikineev via cfe-commits
AntonBikineev updated this revision to Diff 62317.

http://reviews.llvm.org/D21834

Files:
  include/clang/AST/Stmt.h
  include/clang/Sema/Sema.h
  lib/AST/ASTImporter.cpp
  lib/AST/Stmt.cpp
  lib/Analysis/BodyFarm.cpp
  lib/CodeGen/CGStmt.cpp
  lib/Sema/SemaStmt.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp

Index: lib/Serialization/ASTWriterStmt.cpp
===
--- lib/Serialization/ASTWriterStmt.cpp
+++ lib/Serialization/ASTWriterStmt.cpp
@@ -129,6 +129,7 @@
 void ASTStmtWriter::VisitIfStmt(IfStmt *S) {
   VisitStmt(S);
   Record.push_back(S->isConstexpr());
+  Record.AddStmt(S->getInit());
   Record.AddDeclRef(S->getConditionVariable());
   Record.AddStmt(S->getCond());
   Record.AddStmt(S->getThen());
@@ -140,6 +141,7 @@
 
 void ASTStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
   VisitStmt(S);
+  Record.AddStmt(S->getInit());
   Record.AddDeclRef(S->getConditionVariable());
   Record.AddStmt(S->getCond());
   Record.AddStmt(S->getBody());
Index: lib/Serialization/ASTReaderStmt.cpp
===
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -185,6 +185,7 @@
 void ASTStmtReader::VisitIfStmt(IfStmt *S) {
   VisitStmt(S);
   S->setConstexpr(Record[Idx++]);
+  S->setInit(Reader.ReadSubStmt());
   S->setConditionVariable(Reader.getContext(),
   ReadDeclAs(Record, Idx));
   S->setCond(Reader.ReadSubExpr());
@@ -196,6 +197,7 @@
 
 void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) {
   VisitStmt(S);
+  S->setInit(Reader.ReadSubStmt());
   S->setConditionVariable(Reader.getContext(),
   ReadDeclAs(Record, Idx));
   S->setCond(Reader.ReadSubExpr());
Index: lib/Sema/TreeTransform.h
===
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -1174,9 +1174,9 @@
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
   StmtResult RebuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
-   Sema::ConditionResult Cond, Stmt *Then,
+   Sema::ConditionResult Cond, Stmt *Init, Stmt *Then,
SourceLocation ElseLoc, Stmt *Else) {
-return getSema().ActOnIfStmt(IfLoc, IsConstexpr, nullptr, Cond, Then,
+return getSema().ActOnIfStmt(IfLoc, IsConstexpr, Init, Cond, Then,
  ElseLoc, Else);
   }
 
@@ -1185,8 +1185,9 @@
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
   StmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc,
+Stmt *Init,
 Sema::ConditionResult Cond) {
-return getSema().ActOnStartOfSwitchStmt(SwitchLoc, nullptr, Cond);
+return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Init, Cond);
   }
 
   /// \brief Attach the body to the switch statement.
@@ -6236,6 +6237,11 @@
 template
 StmtResult
 TreeTransform::TransformIfStmt(IfStmt *S) {
+  // Transform the initialization statement
+  StmtResult Init = getDerived().TransformStmt(S->getInit());
+  if (Init.isInvalid())
+return StmtError();
+
   // Transform the condition
   Sema::ConditionResult Cond = getDerived().TransformCondition(
   S->getIfLoc(), S->getConditionVariable(), S->getCond(),
@@ -6268,6 +6274,7 @@
   }
 
   if (!getDerived().AlwaysRebuild() &&
+  Init.get() == S->getInit() &&
   Cond.get() == std::make_pair(S->getConditionVariable(), S->getCond()) &&
   Then.get() == S->getThen() &&
   Else.get() == S->getElse())
@@ -6274,12 +6281,17 @@
 return S;
 
   return getDerived().RebuildIfStmt(S->getIfLoc(), S->isConstexpr(), Cond,
-Then.get(), S->getElseLoc(), Else.get());
+Init.get(), Then.get(), S->getElseLoc(), Else.get());
 }
 
 template
 StmtResult
 TreeTransform::TransformSwitchStmt(SwitchStmt *S) {
+  // Transform the initialization statement
+  StmtResult Init = getDerived().TransformStmt(S->getInit());
+  if (Init.isInvalid())
+return StmtError();
+
   // Transform the condition.
   Sema::ConditionResult Cond = getDerived().TransformCondition(
   S->getSwitchLoc(), S->getConditionVariable(), S->getCond(),
@@ -6289,7 +6301,8 @@
 
   // Rebuild the switch statement.
   StmtResult Switch
-= getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), Cond);
+= getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(),
+  S->getInit(), Cond);
   if (Switch.isInvalid())
 return StmtError();
 
Index: lib/Sema/SemaStmt.cpp
===
--- 

Re: [PATCH] D21834: Implementing 'If statement with Initializer'

2016-06-29 Thread Anton Bikineev via cfe-commits
AntonBikineev added a comment.

@rsmith,

> This is not correct; TryParseSimpleDeclaration usually stops long before it 
> reaches the end of the simple-declaration, so this will give false negatives 
> in lots of cases.


Yes, I noticed that, that's why I changed use of TryParseSimpleDeclaration to 
something easier in last revision.

Thanks for reply, Richard. The revision you sent looks great, I should have 
updated my working copy before :)
Anyways, there are not too much of changes to Sema/AST stuff, I just applied 
them on top of yours, added the same for SwitchStmt. I'll update the test you 
put according to my changes tomorrow.


http://reviews.llvm.org/D21834



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21834: Implementing 'If statement with Initializer'

2016-06-29 Thread Anton Bikineev via cfe-commits
AntonBikineev added a subscriber: cfe-commits.
AntonBikineev updated this revision to Diff 62254.

http://reviews.llvm.org/D21834

Files:
  include/clang/AST/Stmt.h
  include/clang/Parse/Parser.h
  include/clang/Sema/Sema.h
  lib/AST/ASTImporter.cpp
  lib/AST/Stmt.cpp
  lib/Analysis/BodyFarm.cpp
  lib/CodeGen/CGStmt.cpp
  lib/Parse/ParseStmt.cpp
  lib/Parse/ParseTentative.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprCXX.cpp
  lib/Sema/SemaStmt.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp

Index: lib/Serialization/ASTWriterStmt.cpp
===
--- lib/Serialization/ASTWriterStmt.cpp
+++ lib/Serialization/ASTWriterStmt.cpp
@@ -129,6 +129,7 @@
 void ASTStmtWriter::VisitIfStmt(IfStmt *S) {
   VisitStmt(S);
   Record.push_back(S->isConstexpr());
+  Record.AddStmt(S->getInit());
   Record.AddDeclRef(S->getConditionVariable());
   Record.AddStmt(S->getCond());
   Record.AddStmt(S->getThen());
Index: lib/Serialization/ASTReaderStmt.cpp
===
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -185,6 +185,7 @@
 void ASTStmtReader::VisitIfStmt(IfStmt *S) {
   VisitStmt(S);
   S->setConstexpr(Record[Idx++]);
+  S->setInit(Reader.ReadSubStmt());
   S->setConditionVariable(Reader.getContext(),
   ReadDeclAs(Record, Idx));
   S->setCond(Reader.ReadSubExpr());
Index: lib/Sema/TreeTransform.h
===
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -1174,9 +1174,9 @@
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
   StmtResult RebuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
-   Sema::ConditionResult Cond, Stmt *Then,
+   Sema::ConditionResult Cond, Stmt *Init, Stmt *Then,
SourceLocation ElseLoc, Stmt *Else) {
-return getSema().ActOnIfStmt(IfLoc, IsConstexpr, Cond, Then, ElseLoc, Else);
+return getSema().ActOnIfStmt(IfLoc, IsConstexpr, Cond, Init, Then, ElseLoc, Else);
   }
 
   /// \brief Start building a new switch statement.
@@ -6225,6 +6225,11 @@
 template
 StmtResult
 TreeTransform::TransformIfStmt(IfStmt *S) {
+  // Transform the initialization statement
+  StmtResult Init = getDerived().TransformStmt(S->getInit());
+  if (Init.isInvalid())
+return StmtError();
+
   // Transform the condition
   Sema::ConditionResult Cond = getDerived().TransformCondition(
   S->getIfLoc(), S->getConditionVariable(), S->getCond(),
@@ -6257,6 +6262,7 @@
   }
 
   if (!getDerived().AlwaysRebuild() &&
+  Init.get() == S->getInit() &&
   Cond.get() == std::make_pair(S->getConditionVariable(), S->getCond()) &&
   Then.get() == S->getThen() &&
   Else.get() == S->getElse())
@@ -6263,7 +6269,7 @@
 return S;
 
   return getDerived().RebuildIfStmt(S->getIfLoc(), S->isConstexpr(), Cond,
-Then.get(), S->getElseLoc(), Else.get());
+Init.get(), Then.get(), S->getElseLoc(), Else.get());
 }
 
 template
Index: lib/Sema/SemaStmt.cpp
===
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -505,7 +505,7 @@
 
 StmtResult
 Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, ConditionResult Cond,
-  Stmt *thenStmt, SourceLocation ElseLoc,
+  Stmt *initStmt, Stmt *thenStmt, SourceLocation ElseLoc,
   Stmt *elseStmt) {
   if (Cond.isInvalid())
 Cond = ConditionResult(
@@ -524,11 +524,11 @@
 DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), thenStmt,
   diag::warn_empty_if_body);
 
-  return BuildIfStmt(IfLoc, IsConstexpr, Cond, thenStmt, ElseLoc, elseStmt);
+  return BuildIfStmt(IfLoc, IsConstexpr, Cond, initStmt, thenStmt, ElseLoc, elseStmt);
 }
 
 StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
- ConditionResult Cond, Stmt *thenStmt,
+ ConditionResult Cond, Stmt *initStmt, Stmt *thenStmt,
  SourceLocation ElseLoc, Stmt *elseStmt) {
   if (Cond.isInvalid())
 return StmtError();
@@ -539,7 +539,7 @@
   DiagnoseUnusedExprResult(thenStmt);
   DiagnoseUnusedExprResult(elseStmt);
 
-  return new (Context) IfStmt(Context, IfLoc, IsConstexpr, Cond.get().first,
+  return new (Context) IfStmt(Context, IfLoc, IsConstexpr, initStmt, Cond.get().first,
   Cond.get().second, thenStmt, ElseLoc, elseStmt);
 }
 
Index: lib/Sema/SemaExprCXX.cpp
===
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -3095,6 +3095,7 @@
 
   switch 

Re: [PATCH] D5744: Partial specialization after class template instantiation.

2015-12-14 Thread Anton Bikineev via cfe-commits
AntonBikineev added a comment.

@rsmith, are there any plans/suggestions regarding this patch?


http://reviews.llvm.org/D5744



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits