Re: [PATCH] D13344: Keep the IfStmt node even if the condition is invalid

2015-10-10 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

Are the analysis run if there is an error?  I think the consumer should expect 
null condition anyway.

But i'll try to add an ErrorExpr anyway.


http://reviews.llvm.org/D13344



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


r249982 - Keep the IfStmt node even if the condition is invalid

2015-10-11 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Sun Oct 11 12:27:29 2015
New Revision: 249982

URL: http://llvm.org/viewvc/llvm-project?rev=249982=rev
Log:
Keep the IfStmt node even if the condition is invalid

This is important to keep the information in IDE or other tools
even if the code contains a few errors

Modified:
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/test/Misc/ast-dump-invalid.cpp

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=249982=249981=249982=diff
==
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Sun Oct 11 12:27:29 2015
@@ -483,13 +483,6 @@ StmtResult
 Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
   Stmt *thenStmt, SourceLocation ElseLoc,
   Stmt *elseStmt) {
-  // If the condition was invalid, discard the if statement.  We could recover
-  // better by replacing it with a valid expr, but don't do that yet.
-  if (!CondVal.get() && !CondVar) {
-getCurFunction()->setHasDroppedStmt();
-return StmtError();
-  }
-
   ExprResult CondResult(CondVal.release());
 
   VarDecl *ConditionVar = nullptr;
@@ -497,22 +490,23 @@ Sema::ActOnIfStmt(SourceLocation IfLoc,
 ConditionVar = cast(CondVar);
 CondResult = CheckConditionVariable(ConditionVar, IfLoc, true);
 CondResult = ActOnFinishFullExpr(CondResult.get(), IfLoc);
-if (CondResult.isInvalid())
-  return StmtError();
   }
   Expr *ConditionExpr = CondResult.getAs();
-  if (!ConditionExpr)
-return StmtError();
+  if (ConditionExpr) {
+DiagnoseUnusedExprResult(thenStmt);
 
-  DiagnoseUnusedExprResult(thenStmt);
-
-  if (!elseStmt) {
-DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt,
-  diag::warn_empty_if_body);
+if (!elseStmt) {
+  DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt,
+diag::warn_empty_if_body);
+}
+
+DiagnoseUnusedExprResult(elseStmt);
+  } else {
+// Create a dummy Expr for the condition for error recovery
+ConditionExpr = new (Context) OpaqueValueExpr(SourceLocation(),
+  Context.BoolTy, VK_RValue);
   }
 
-  DiagnoseUnusedExprResult(elseStmt);
-
   return new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr,
   thenStmt, ElseLoc, elseStmt);
 }

Modified: cfe/trunk/test/Misc/ast-dump-invalid.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-invalid.cpp?rev=249982=249981=249982=diff
==
--- cfe/trunk/test/Misc/ast-dump-invalid.cpp (original)
+++ cfe/trunk/test/Misc/ast-dump-invalid.cpp Sun Oct 11 12:27:29 2015
@@ -18,3 +18,26 @@ void f(T i, T j) {
 // CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}}  'T'
 // CHECK-NEXT:   |-DeclRefExpr {{.*}}  'T' lvalue ParmVar 
{{.*}} 'i' 'T'
 // CHECK-NEXT:   `-DeclRefExpr {{.*}}  'T' lvalue ParmVar 
{{.*}} 'j' 'T'
+
+
+namespace TestInvalidIf {
+int g(int i) {
+  if (invalid_condition)
+return 4;
+  else
+return i;
+}
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf
+// CHECK-NEXT: `-FunctionDecl
+// CHECK-NEXT:   |-ParmVarDecl
+// CHECK-NEXT:   `-CompoundStmt
+// CHECK-NEXT: `-IfStmt {{.*}} 
+// CHECK-NEXT:   |-<<>>
+// CHECK-NEXT:   |-OpaqueValueExpr {{.*}} <> '_Bool'
+// CHECK-NEXT:   |-ReturnStmt {{.*}} 
+// CHECK-NEXT:   | `-IntegerLiteral {{.*}}  'int' 4
+// CHECK-NEXT:   `-ReturnStmt {{.*}} 
+// CHECK-NEXT: `-ImplicitCastExpr {{.*}}  'int' 

+// CHECK-NEXT:   `-DeclRefExpr {{.*}}  'int' lvalue ParmVar 
{{.*}} 'i' 'int'
+


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


Re: [PATCH] D13344: Keep the IfStmt node even if the condition is invalid

2015-10-11 Thread Olivier Goffart via cfe-commits
ogoffart abandoned this revision.
ogoffart marked an inline comment as done.
ogoffart added a comment.

commited as r249982. (I forgot to add the link to reviews.llvm.org in the 
commit message. I'll do it next time)


http://reviews.llvm.org/D13344



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


r246844 - Fix the perentheses location when the constructor is called on a class that has a destructor

2015-09-04 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Fri Sep  4 05:17:10 2015
New Revision: 246844

URL: http://llvm.org/viewvc/llvm-project?rev=246844=rev
Log:
Fix the perentheses location when the constructor is called on a class that has 
a destructor

Modified:
cfe/trunk/lib/Sema/SemaCast.cpp
cfe/trunk/test/SemaCXX/sourceranges.cpp

Modified: cfe/trunk/lib/Sema/SemaCast.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=246844=246843=246844=diff
==
--- cfe/trunk/lib/Sema/SemaCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCast.cpp Fri Sep  4 05:17:10 2015
@@ -2483,8 +2483,11 @@ ExprResult Sema::BuildCXXFunctionalCastE
   Op.CheckCXXCStyleCast(/*FunctionalStyle=*/true, /*ListInit=*/false);
   if (Op.SrcExpr.isInvalid())
 return ExprError();
-  
-  if (CXXConstructExpr *ConstructExpr = 
dyn_cast(Op.SrcExpr.get()))
+
+  auto *SubExpr = Op.SrcExpr.get();
+  if (auto *BindExpr = dyn_cast(SubExpr))
+SubExpr = BindExpr->getSubExpr();
+  if (auto *ConstructExpr = dyn_cast(SubExpr))
 ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc));
 
   return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType,

Modified: cfe/trunk/test/SemaCXX/sourceranges.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/sourceranges.cpp?rev=246844=246843=246844=diff
==
--- cfe/trunk/test/SemaCXX/sourceranges.cpp (original)
+++ cfe/trunk/test/SemaCXX/sourceranges.cpp Fri Sep  4 05:17:10 2015
@@ -7,7 +7,7 @@ class P {
 };
 
 namespace foo {
-class A { public: A() {} };
+class A { public: A(int = 0) {} };
 enum B {};
 typedef int C;
 }
@@ -37,3 +37,16 @@ void destruct(foo::A *a1, foo::A *a2, P<
   // CHECK: MemberExpr {{0x[0-9a-fA-F]+}}  '' ->~P
   p1->~P();
 }
+
+struct D {
+  D(int);
+  ~D();
+};
+
+void construct() {
+  using namespace foo;
+  A a = A(12);
+  // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}}  'class foo::A' 
'void (int)'
+  D d = D(12);
+  // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}}  'struct D' 
'void (int)'
+}


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


Re: [PATCH] fix parentheses location in a CXXConstructExpr

2015-09-03 Thread Olivier Goffart via cfe-commits
On Thursday 3. September 2015 13:41:12 Richard Smith wrote:
> On Thu, Sep 3, 2015 at 8:58 AM, Manuel Klimek <kli...@google.com> wrote:
> > On Tue, Sep 1, 2015 at 12:31 AM Olivier Goffart <ogoff...@kde.org> wrote:
> >> On Monday 31. August 2015 08:07:58 Manuel Klimek wrote:
> >> > On Sat, Aug 29, 2015 at 12:23 PM Olivier Goffart via cfe-commits <
> >> > 
> >> > cfe-commits@lists.llvm.org> wrote:
> >> > > Hi,
> >> > > 
> >> > > Please review the attached patch.
> >> > > 
> >> > > In Sema::BuildCXXFunctionalCastExpr, if the class has a destructor,
> >> 
> >> the
> >> 
> >> > > Op.SrcExpr might be a CXXBindTemporaryExpr which we need to unwrap.
> >> > > 
> >> > > In the testcase, the first new CHECK worked (because A does not have
> >> > > a
> >> > > destructor),  but the second CHECK failed (did not include the last
> >> > > parenthese) because D has a destructor.
> >> > > 
> >> > > I used dyn_cast_or_null just to be safe, becasue i don't know if it
> >> > > is
> >> > > possible for the BindExpr->getSubExpr() to be null.
> >> > 
> >> > Do you know why the added test for A says 'class foo::A' instead of
> >> > 'foo::A' as the other tests do in that file?
> >> 
> >> I don't know.  It seems it has to do with the fully quallified name vs.
> >> normal
> >> name.
> >> 
> >> For example, if you dumpt the AST of:
> >>  namespace foo { class A {} *a1 = new foo::A , *a2 = new A; }
> >> 
> >> You get:
> >> 
> >> [...]
> >> 
> >> | |-VarDecl 0x1c9a7a0 <col:17, col:43> col:29 a1 'class A *' cinit
> >> | |
> >> | | `-CXXNewExpr 0x1ce2648 <col:34, col:43> 'foo::A *'
> >> | | 
> >> | |   `-CXXConstructExpr 0x1ce2618  'foo::A':'class foo::A' 'void
> >> 
> >> (void) throw()'
> >> 
> >> | `-VarDecl 0x1ce26d0 <col:17, col:57> col:48 a2 'class A *' cinit
> >> | 
> >> |   `-CXXNewExpr 0x1ce2768 <col:53, col:57> 'class foo::A *'
> >> |   
> >> | `-CXXConstructExpr 0x1ce2738  'class foo::A' 'void (void)
> >> 
> >> throw()'
> >> 
> >> 
> >> As you can see, when the type of CXXNewExpr is fully quialified, the
> >> 'class'
> >> keyword is omited, but for a2, it prints the 'class' keyword.
> >> The printed type of CXXConstructExpr is even more wierd when it is fully
> >> qualified.
> >> 
> >> 
> >> I guess that's because of ElaboratedTypePolicyRAII in TypePrinter.cpp
> >> 
> >> But this is irrelevant for this patch and the problem it's trying to
> >> solve.
> >> The reason I used 'using namespace foo' in the test was just so the line
> >> with
> >> A and D have the same size.   I just copy pasted the thing without
> >> thinking
> >> about that.
> > 
> > Makes sense. In that case I think it looks good, adding Richard to
> > cross-check for the final approval.
> 
> +  auto ConstructExpr = dyn_cast(Op.SrcExpr.get());
> +  if (auto BindExpr = dyn_cast(Op.SrcExpr.get()))
> +ConstructExpr =
> dyn_cast_or_null(BindExpr->getSubExpr());
> +  if (ConstructExpr)
> 
> It's slightly better to write this as:
> 
>   auto *SubExpr = Op.SrcExpr.get();
>   if (auto *BindExpr = dyn_cast(SubExpr))
> SubExpr = BindExpr->getSubExpr();
>   if (auto *ConstructExpr = dyn_cast(SubExpr))
> 
> Otherwise, LGTM.


Thanks.

So no dyn_cast_or_null?   CXXBindTemporaryExpr::getSubExpr never returns null 
here?

> [The root cause of the problem here is suboptimal design of this AST node.
> It doesn't make sense for both CXXFunctionalCastExpr and CXXConstructExpr
> to hold the locations of the same set of parens (and we can see from
> StmtPrinter that CXXFunctionalCastExpr currently "owns" the parens). But
> fixing that is a larger task, so let's just get this immediate bug fixed
> for now.]

[This is however quite convnient for me to get the location of the parentheses 
of a CXXConstructorExpr. There are may cases where CXXConstructorExpr is not 
in a CXXFunctionalCastExpr]

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


[PATCH] Keep the IfStmt node even if the condition is invalid

2015-09-29 Thread Olivier Goffart via cfe-commits
Hi, 

Please review the attached patch. It does not discard the full 'if' statement 
if the condition is invalid.

This is quite useful for IDE's or other tools which would like to recover as 
much as possible even if there are a few errors in the code, and discarding 
the full 'if' bodies is unfortunate.

Thanks.
-- 
Olivier


P.S: For the same reason, i'm also trying to fix the fact that if there is any 
typo in an expression statement, the full statement is discarded. The reason 
is i believe that Sema::CorrectDelayedTyposInExpr just return null if any typo 
could not be corrected. That's unrelated to this patch, but i still would 
welcome hint on how to fix it.  Should CorrectDelayedTyposInExpr somehow 
replace the TypoExpr instead of removing them? Or should it create a new node 
(some kind of error ErrorExpr)? Or should the caller of 
CorrectDelayedTyposInExpr be changed to keep the original?
>From 8f5f74755cfa0c6165caff65dcc07b0d2543f481 Mon Sep 17 00:00:00 2001
From: Olivier Goffart 
Date: Sat, 12 Sep 2015 16:09:34 +0200
Subject: [PATCH] Keep the IfStmt node even if the condition is invalid

This is important to keep the information in IDE or other tools
even if the code contains a few errors
---
 lib/Sema/SemaStmt.cpp  | 22 +++---
 test/Misc/ast-dump-invalid.cpp | 23 +++
 2 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index c39c80d..97a1160 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -483,13 +483,6 @@ StmtResult
 Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
   Stmt *thenStmt, SourceLocation ElseLoc,
   Stmt *elseStmt) {
-  // If the condition was invalid, discard the if statement.  We could recover
-  // better by replacing it with a valid expr, but don't do that yet.
-  if (!CondVal.get() && !CondVar) {
-getCurFunction()->setHasDroppedStmt();
-return StmtError();
-  }
-
   ExprResult CondResult(CondVal.release());
 
   VarDecl *ConditionVar = nullptr;
@@ -501,18 +494,17 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
   return StmtError();
   }
   Expr *ConditionExpr = CondResult.getAs();
-  if (!ConditionExpr)
-return StmtError();
+  if (ConditionExpr) {
+DiagnoseUnusedExprResult(thenStmt);
 
-  DiagnoseUnusedExprResult(thenStmt);
+if (!elseStmt) {
+  DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt,
+diag::warn_empty_if_body);
+}
 
-  if (!elseStmt) {
-DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt,
-  diag::warn_empty_if_body);
+DiagnoseUnusedExprResult(elseStmt);
   }
 
-  DiagnoseUnusedExprResult(elseStmt);
-
   return new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr,
   thenStmt, ElseLoc, elseStmt);
 }
diff --git a/test/Misc/ast-dump-invalid.cpp b/test/Misc/ast-dump-invalid.cpp
index 3b97cc6..899bfa0 100644
--- a/test/Misc/ast-dump-invalid.cpp
+++ b/test/Misc/ast-dump-invalid.cpp
@@ -18,3 +18,26 @@ void f(T i, T j) {
 // CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}}  'T'
 // CHECK-NEXT:   |-DeclRefExpr {{.*}}  'T' lvalue ParmVar {{.*}} 'i' 'T'
 // CHECK-NEXT:   `-DeclRefExpr {{.*}}  'T' lvalue ParmVar {{.*}} 'j' 'T'
+
+
+namespace TestInvalidIf {
+int g(int i) {
+  if (invalid_condition)
+return 4;
+  else
+return i;
+}
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf
+// CHECK-NEXT: `-FunctionDecl
+// CHECK-NEXT:   |-ParmVarDecl
+// CHECK-NEXT:   `-CompoundStmt
+// CHECK-NEXT: `-IfStmt {{.*}} 
+// CHECK-NEXT:   |-<<>>
+// CHECK-NEXT:   |-<<>>
+// CHECK-NEXT:   |-ReturnStmt {{.*}} 
+// CHECK-NEXT:   | `-IntegerLiteral {{.*}}  'int' 4
+// CHECK-NEXT:   `-ReturnStmt {{.*}} 
+// CHECK-NEXT: `-ImplicitCastExpr {{.*}}  'int' 
+// CHECK-NEXT:   `-DeclRefExpr {{.*}}  'int' lvalue ParmVar {{.*}} 'i' 'int'
+
-- 
2.6.0

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


[PATCH] D13344: Keep the IfStmt node even if the condition is invalid

2015-10-01 Thread Olivier Goffart via cfe-commits
ogoffart created this revision.
ogoffart added a reviewer: cfe-commits.

This is quite useful for IDE's or other tools which would like to recover as 
much as possible even if there are a few errors in the code, and discarding 
the full 'if' bodies is unfortunate.

http://reviews.llvm.org/D13344

Files:
  lib/Sema/SemaStmt.cpp
  test/Misc/ast-dump-invalid.cpp

Index: test/Misc/ast-dump-invalid.cpp
===
--- test/Misc/ast-dump-invalid.cpp
+++ test/Misc/ast-dump-invalid.cpp
@@ -18,3 +18,26 @@
 // CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}}  'T'
 // CHECK-NEXT:   |-DeclRefExpr {{.*}}  'T' lvalue ParmVar 
{{.*}} 'i' 'T'
 // CHECK-NEXT:   `-DeclRefExpr {{.*}}  'T' lvalue ParmVar 
{{.*}} 'j' 'T'
+
+
+namespace TestInvalidIf {
+int g(int i) {
+  if (invalid_condition)
+return 4;
+  else
+return i;
+}
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf
+// CHECK-NEXT: `-FunctionDecl
+// CHECK-NEXT:   |-ParmVarDecl
+// CHECK-NEXT:   `-CompoundStmt
+// CHECK-NEXT: `-IfStmt {{.*}} 
+// CHECK-NEXT:   |-<<>>
+// CHECK-NEXT:   |-<<>>
+// CHECK-NEXT:   |-ReturnStmt {{.*}} 
+// CHECK-NEXT:   | `-IntegerLiteral {{.*}}  'int' 4
+// CHECK-NEXT:   `-ReturnStmt {{.*}} 
+// CHECK-NEXT: `-ImplicitCastExpr {{.*}}  'int' 

+// CHECK-NEXT:   `-DeclRefExpr {{.*}}  'int' lvalue ParmVar 
{{.*}} 'i' 'int'
+
Index: lib/Sema/SemaStmt.cpp
===
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -483,13 +483,6 @@
 Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
   Stmt *thenStmt, SourceLocation ElseLoc,
   Stmt *elseStmt) {
-  // If the condition was invalid, discard the if statement.  We could recover
-  // better by replacing it with a valid expr, but don't do that yet.
-  if (!CondVal.get() && !CondVar) {
-getCurFunction()->setHasDroppedStmt();
-return StmtError();
-  }
-
   ExprResult CondResult(CondVal.release());
 
   VarDecl *ConditionVar = nullptr;
@@ -501,18 +494,17 @@
   return StmtError();
   }
   Expr *ConditionExpr = CondResult.getAs();
-  if (!ConditionExpr)
-return StmtError();
+  if (ConditionExpr) {
+DiagnoseUnusedExprResult(thenStmt);
 
-  DiagnoseUnusedExprResult(thenStmt);
+if (!elseStmt) {
+  DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt,
+diag::warn_empty_if_body);
+}
 
-  if (!elseStmt) {
-DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt,
-  diag::warn_empty_if_body);
+DiagnoseUnusedExprResult(elseStmt);
   }
 
-  DiagnoseUnusedExprResult(elseStmt);
-
   return new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr,
   thenStmt, ElseLoc, elseStmt);
 }


Index: test/Misc/ast-dump-invalid.cpp
===
--- test/Misc/ast-dump-invalid.cpp
+++ test/Misc/ast-dump-invalid.cpp
@@ -18,3 +18,26 @@
 // CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}}  'T'
 // CHECK-NEXT:   |-DeclRefExpr {{.*}}  'T' lvalue ParmVar {{.*}} 'i' 'T'
 // CHECK-NEXT:   `-DeclRefExpr {{.*}}  'T' lvalue ParmVar {{.*}} 'j' 'T'
+
+
+namespace TestInvalidIf {
+int g(int i) {
+  if (invalid_condition)
+return 4;
+  else
+return i;
+}
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf
+// CHECK-NEXT: `-FunctionDecl
+// CHECK-NEXT:   |-ParmVarDecl
+// CHECK-NEXT:   `-CompoundStmt
+// CHECK-NEXT: `-IfStmt {{.*}} 
+// CHECK-NEXT:   |-<<>>
+// CHECK-NEXT:   |-<<>>
+// CHECK-NEXT:   |-ReturnStmt {{.*}} 
+// CHECK-NEXT:   | `-IntegerLiteral {{.*}}  'int' 4
+// CHECK-NEXT:   `-ReturnStmt {{.*}} 
+// CHECK-NEXT: `-ImplicitCastExpr {{.*}}  'int' 
+// CHECK-NEXT:   `-DeclRefExpr {{.*}}  'int' lvalue ParmVar {{.*}} 'i' 'int'
+
Index: lib/Sema/SemaStmt.cpp
===
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -483,13 +483,6 @@
 Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
   Stmt *thenStmt, SourceLocation ElseLoc,
   Stmt *elseStmt) {
-  // If the condition was invalid, discard the if statement.  We could recover
-  // better by replacing it with a valid expr, but don't do that yet.
-  if (!CondVal.get() && !CondVar) {
-getCurFunction()->setHasDroppedStmt();
-return StmtError();
-  }
-
   ExprResult CondResult(CondVal.release());
 
   VarDecl *ConditionVar = nullptr;
@@ -501,18 +494,17 @@
   return StmtError();
   }
   Expr *ConditionExpr = CondResult.getAs();
-  if (!ConditionExpr)
-return StmtError();
+  if 

Re: [PATCH] D18081: Make sizeof and alignof a CXCursor_UnaryExpr

2016-06-09 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

Ping 2.


http://reviews.llvm.org/D18081



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


Re: [PATCH] D19763: Functions declared in a scope should not hide previous declaration in earlier scopes

2016-06-09 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

Ping.
This would be required for http://reviews.llvm.org/D19764


http://reviews.llvm.org/D19763



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


Re: [PATCH] D20821: Fix a few issues while skipping function bodies

2016-06-09 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

The idea is that when we see a ") {"  or "} {"  in the ctor-initializers, 
(optionally with "..."), it is necessarily the start of the body.

Unless there might be lambda expressions within a template aregument, as in:


  A::A() : Base<[](){return 42; }()>(){}

But this is not valid because lambda expression cannot appear in this context 
as far as i know since lambda expression cannot appear in template argument


http://reviews.llvm.org/D20821



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


Re: [PATCH] D20821: Fix a few issues while skipping function bodies

2016-06-10 Thread Olivier Goffart via cfe-commits
ogoffart updated this revision to Diff 60340.
ogoffart added a comment.

Using Parser::ConsumeAndStoreFunctionPrologue this time


http://reviews.llvm.org/D20821

Files:
  lib/Parse/ParseCXXInlineMethods.cpp
  lib/Parse/ParseObjc.cpp
  lib/Parse/ParseStmt.cpp
  lib/Parse/Parser.cpp
  lib/Sema/SemaDecl.cpp
  test/CodeCompletion/ctor-initializer.cpp
  unittests/Tooling/ToolingTest.cpp

Index: unittests/Tooling/ToolingTest.cpp
===
--- unittests/Tooling/ToolingTest.cpp
+++ unittests/Tooling/ToolingTest.cpp
@@ -241,7 +241,7 @@
 struct SkipBodyConsumer : public clang::ASTConsumer {
   /// Skip the 'skipMe' function.
   bool shouldSkipFunctionBody(Decl *D) override {
-FunctionDecl *F = dyn_cast(D);
+NamedDecl *F = dyn_cast(D);
 return F && F->getNameAsString() == "skipMe";
   }
 };
@@ -255,10 +255,64 @@
 };
 
 TEST(runToolOnCode, TestSkipFunctionBody) {
+  std::vector Args = {"-std=c++11"};
+
   EXPECT_TRUE(runToolOnCode(new SkipBodyAction,
 "int skipMe() { an_error_here }"));
   EXPECT_FALSE(runToolOnCode(new SkipBodyAction,
  "int skipMeNot() { an_error_here }"));
+
+  // Test constructors with initializers
+  EXPECT_TRUE(runToolOnCodeWithArgs(
+  new SkipBodyAction,
+  "struct skipMe { skipMe() : an_error() { more error } };", Args));
+  EXPECT_TRUE(runToolOnCodeWithArgs(
+  new SkipBodyAction, "struct skipMe { skipMe(); };"
+  "skipMe::skipMe() : an_error([](){;}) { more error }",
+  Args));
+  EXPECT_TRUE(runToolOnCodeWithArgs(
+  new SkipBodyAction, "struct skipMe { skipMe(); };"
+  "skipMe::skipMe() : an_error{[](){;}} { more error }",
+  Args));
+  EXPECT_TRUE(runToolOnCodeWithArgs(
+  new SkipBodyAction,
+  "struct skipMe { skipMe(); };"
+  "skipMe::skipMe() : a>(), f{}, g() { error }",
+  Args));
+  EXPECT_TRUE(runToolOnCodeWithArgs(
+  new SkipBodyAction, "struct skipMe { skipMe() : bases()... { error } };",
+  Args));
+
+  EXPECT_FALSE(runToolOnCodeWithArgs(
+  new SkipBodyAction, "struct skipMeNot { skipMeNot() : an_error() { } };",
+  Args));
+  EXPECT_FALSE(runToolOnCodeWithArgs(new SkipBodyAction,
+ "struct skipMeNot { skipMeNot(); };"
+ "skipMeNot::skipMeNot() : an_error() { }",
+ Args));
+
+  // Try/catch
+  EXPECT_TRUE(runToolOnCode(
+  new SkipBodyAction,
+  "void skipMe() try { an_error() } catch(error) { error };"));
+  EXPECT_TRUE(runToolOnCode(
+  new SkipBodyAction,
+  "struct S { void skipMe() try { an_error() } catch(error) { error } };"));
+  EXPECT_TRUE(
+  runToolOnCode(new SkipBodyAction,
+"void skipMe() try { an_error() } catch(error) { error; }"
+"catch(error) { error } catch (error) { }"));
+  EXPECT_FALSE(runToolOnCode(
+  new SkipBodyAction,
+  "void skipMe() try something;")); // don't crash while parsing
+
+  // Template
+  EXPECT_TRUE(runToolOnCode(
+  new SkipBodyAction, "template int skipMe() { an_error_here }"
+  "int x = skipMe();"));
+  EXPECT_FALSE(
+  runToolOnCode(new SkipBodyAction,
+"template int skipMeNot() { an_error_here }"));
 }
 
 TEST(runToolOnCodeWithArgs, TestNoDepFile) {
Index: test/CodeCompletion/ctor-initializer.cpp
===
--- /dev/null
+++ test/CodeCompletion/ctor-initializer.cpp
@@ -0,0 +1,41 @@
+struct Base1 {
+  Base1() : {}
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: COMPLETION: Pattern : member1(<#args#>)
+  // CHECK-CC1: COMPLETION: Pattern : member2(<#args#>
+
+  Base1(int) : member1(123), {}
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:7:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+  // CHECK-CC2-NOT: COMPLETION: Pattern : member1(<#args#>)
+  // CHECK-CC2: COMPLETION: Pattern : member2(<#args#>
+
+  int member1;
+  float member2;
+};
+
+struct Derived : public Base1 {
+  Derived();
+  Derived(int);
+  Derived(float);
+  int deriv1;
+};
+
+Derived::Derived() : {}
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: COMPLETION: Pattern : Base1(<#args#>)
+// CHECK-CC3: COMPLETION: Pattern : deriv1(<#args#>)
+
+Derived::Derived(int) try : {
+} catch (...) {
+}
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:28:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC4: COMPLETION: Pattern : Base1(<#args#>)
+// CHECK-CC4: COMPLETION: Pattern : deriv1(<#args#>)
+
+Derived::Derived(float) try : Base1(),
+{
+} catch (...) {
+}
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:35:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
+// 

Re: [PATCH] D18081: Make sizeof and alignof a CXCursor_UnaryExpr

2016-06-09 Thread Olivier Goffart via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL272274: Make sizeof and alignof a CXCursor_UnaryExpr 
(authored by ogoffart).

Changed prior to commit:
  http://reviews.llvm.org/D18081?vs=50408=60187#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D18081

Files:
  cfe/trunk/include/clang-c/Index.h
  cfe/trunk/test/Index/annotate-tokens.c
  cfe/trunk/tools/libclang/CXCursor.cpp

Index: cfe/trunk/tools/libclang/CXCursor.cpp
===
--- cfe/trunk/tools/libclang/CXCursor.cpp
+++ cfe/trunk/tools/libclang/CXCursor.cpp
@@ -256,7 +256,6 @@
   case Stmt::PredefinedExprClass:
   case Stmt::ShuffleVectorExprClass:
   case Stmt::ConvertVectorExprClass:
-  case Stmt::UnaryExprOrTypeTraitExprClass:
   case Stmt::VAArgExprClass:
   case Stmt::ObjCArrayLiteralClass:
   case Stmt::ObjCDictionaryLiteralClass:
@@ -327,6 +326,7 @@
 K = CXCursor_UnaryOperator;
 break;
 
+  case Stmt::UnaryExprOrTypeTraitExprClass:
   case Stmt::CXXNoexceptExprClass:
 K = CXCursor_UnaryExpr;
 break;
Index: cfe/trunk/include/clang-c/Index.h
===
--- cfe/trunk/include/clang-c/Index.h
+++ cfe/trunk/include/clang-c/Index.h
@@ -1932,7 +1932,7 @@
*/
   CXCursor_CXXDeleteExpr = 135,
 
-  /** \brief A unary expression.
+  /** \brief A unary expression. (noexcept, sizeof, or other traits)
*/
   CXCursor_UnaryExpr = 136,
 
Index: cfe/trunk/test/Index/annotate-tokens.c
===
--- cfe/trunk/test/Index/annotate-tokens.c
+++ cfe/trunk/test/Index/annotate-tokens.c
@@ -80,10 +80,10 @@
 // CHECK: Punctuation: "(" [5:3 - 5:4] CStyleCastExpr=
 // CHECK: Keyword: "void" [5:4 - 5:8] CStyleCastExpr=
 // CHECK: Punctuation: ")" [5:8 - 5:9] CStyleCastExpr=
-// CHECK: Keyword: "sizeof" [5:9 - 5:15] UnexposedExpr=
-// CHECK: Punctuation: "(" [5:15 - 5:16] UnexposedExpr=
+// CHECK: Keyword: "sizeof" [5:9 - 5:15] UnaryExpr=
+// CHECK: Punctuation: "(" [5:15 - 5:16] UnaryExpr=
 // CHECK: Identifier: "T" [5:16 - 5:17] TypeRef=T:1:13
-// CHECK: Punctuation: ")" [5:17 - 5:18] UnexposedExpr=
+// CHECK: Punctuation: ")" [5:17 - 5:18] UnaryExpr=
 // CHECK: Punctuation: ";" [5:18 - 5:19] CompoundStmt=
 // CHECK: Keyword: "struct" [7:3 - 7:9] VarDecl=x:7:12 (Definition)
 // CHECK: Identifier: "X" [7:10 - 7:11] TypeRef=struct X:2:8


Index: cfe/trunk/tools/libclang/CXCursor.cpp
===
--- cfe/trunk/tools/libclang/CXCursor.cpp
+++ cfe/trunk/tools/libclang/CXCursor.cpp
@@ -256,7 +256,6 @@
   case Stmt::PredefinedExprClass:
   case Stmt::ShuffleVectorExprClass:
   case Stmt::ConvertVectorExprClass:
-  case Stmt::UnaryExprOrTypeTraitExprClass:
   case Stmt::VAArgExprClass:
   case Stmt::ObjCArrayLiteralClass:
   case Stmt::ObjCDictionaryLiteralClass:
@@ -327,6 +326,7 @@
 K = CXCursor_UnaryOperator;
 break;
 
+  case Stmt::UnaryExprOrTypeTraitExprClass:
   case Stmt::CXXNoexceptExprClass:
 K = CXCursor_UnaryExpr;
 break;
Index: cfe/trunk/include/clang-c/Index.h
===
--- cfe/trunk/include/clang-c/Index.h
+++ cfe/trunk/include/clang-c/Index.h
@@ -1932,7 +1932,7 @@
*/
   CXCursor_CXXDeleteExpr = 135,
 
-  /** \brief A unary expression.
+  /** \brief A unary expression. (noexcept, sizeof, or other traits)
*/
   CXCursor_UnaryExpr = 136,
 
Index: cfe/trunk/test/Index/annotate-tokens.c
===
--- cfe/trunk/test/Index/annotate-tokens.c
+++ cfe/trunk/test/Index/annotate-tokens.c
@@ -80,10 +80,10 @@
 // CHECK: Punctuation: "(" [5:3 - 5:4] CStyleCastExpr=
 // CHECK: Keyword: "void" [5:4 - 5:8] CStyleCastExpr=
 // CHECK: Punctuation: ")" [5:8 - 5:9] CStyleCastExpr=
-// CHECK: Keyword: "sizeof" [5:9 - 5:15] UnexposedExpr=
-// CHECK: Punctuation: "(" [5:15 - 5:16] UnexposedExpr=
+// CHECK: Keyword: "sizeof" [5:9 - 5:15] UnaryExpr=
+// CHECK: Punctuation: "(" [5:15 - 5:16] UnaryExpr=
 // CHECK: Identifier: "T" [5:16 - 5:17] TypeRef=T:1:13
-// CHECK: Punctuation: ")" [5:17 - 5:18] UnexposedExpr=
+// CHECK: Punctuation: ")" [5:17 - 5:18] UnaryExpr=
 // CHECK: Punctuation: ";" [5:18 - 5:19] CompoundStmt=
 // CHECK: Keyword: "struct" [7:3 - 7:9] VarDecl=x:7:12 (Definition)
 // CHECK: Identifier: "X" [7:10 - 7:11] TypeRef=struct X:2:8
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18080: CIndex: add support for static_assert

2016-06-09 Thread Olivier Goffart via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL272273: CIndex: add support for static_assert (authored by 
ogoffart).

Changed prior to commit:
  http://reviews.llvm.org/D18080?vs=50407=60186#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D18080

Files:
  cfe/trunk/include/clang-c/Index.h
  cfe/trunk/lib/Sema/SemaCodeComplete.cpp
  cfe/trunk/tools/libclang/CIndex.cpp
  cfe/trunk/tools/libclang/CursorVisitor.h

Index: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
===
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp
@@ -3044,6 +3044,7 @@
 case Decl::ClassTemplatePartialSpecialization:
   return CXCursor_ClassTemplatePartialSpecialization;
 case Decl::UsingDirective: return CXCursor_UsingDirective;
+case Decl::StaticAssert:   return CXCursor_StaticAssert;
 case Decl::TranslationUnit:return CXCursor_TranslationUnit;
   
 case Decl::Using:
Index: cfe/trunk/tools/libclang/CursorVisitor.h
===
--- cfe/trunk/tools/libclang/CursorVisitor.h
+++ cfe/trunk/tools/libclang/CursorVisitor.h
@@ -238,6 +238,7 @@
   bool VisitUsingDecl(UsingDecl *D);
   bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
   bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+  bool VisitStaticAssertDecl(StaticAssertDecl *D);
   
   // Name visitor
   bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
Index: cfe/trunk/tools/libclang/CIndex.cpp
===
--- cfe/trunk/tools/libclang/CIndex.cpp
+++ cfe/trunk/tools/libclang/CIndex.cpp
@@ -1230,6 +1230,14 @@
   return false;
 }
 
+bool CursorVisitor::VisitStaticAssertDecl(StaticAssertDecl *D) {
+  if (Visit(MakeCXCursor(D->getAssertExpr(), StmtParent, TU, 
RegionOfInterest)))
+return true;
+  if (Visit(MakeCXCursor(D->getMessage(), StmtParent, TU, RegionOfInterest)))
+return true;
+  return false;
+}
+
 bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
   switch (Name.getName().getNameKind()) {
   case clang::DeclarationName::Identifier:
@@ -4822,6 +4830,8 @@
   return cxstring::createRef("OverloadCandidate");
   case CXCursor_TypeAliasTemplateDecl:
   return cxstring::createRef("TypeAliasTemplateDecl");
+  case CXCursor_StaticAssert:
+  return cxstring::createRef("StaticAssert");
   }
 
   llvm_unreachable("Unhandled CXCursorKind");
Index: cfe/trunk/include/clang-c/Index.h
===
--- cfe/trunk/include/clang-c/Index.h
+++ cfe/trunk/include/clang-c/Index.h
@@ -2359,8 +2359,12 @@
*/
   CXCursor_ModuleImportDecl  = 600,
   CXCursor_TypeAliasTemplateDecl = 601,
+  /**
+   * \brief A static_assert or _Static_assert node
+   */
+  CXCursor_StaticAssert  = 602,
   CXCursor_FirstExtraDecl= CXCursor_ModuleImportDecl,
-  CXCursor_LastExtraDecl = CXCursor_TypeAliasTemplateDecl,
+  CXCursor_LastExtraDecl = CXCursor_StaticAssert,
 
   /**
* \brief A code completion overload candidate.


Index: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
===
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp
@@ -3044,6 +3044,7 @@
 case Decl::ClassTemplatePartialSpecialization:
   return CXCursor_ClassTemplatePartialSpecialization;
 case Decl::UsingDirective: return CXCursor_UsingDirective;
+case Decl::StaticAssert:   return CXCursor_StaticAssert;
 case Decl::TranslationUnit:return CXCursor_TranslationUnit;
   
 case Decl::Using:
Index: cfe/trunk/tools/libclang/CursorVisitor.h
===
--- cfe/trunk/tools/libclang/CursorVisitor.h
+++ cfe/trunk/tools/libclang/CursorVisitor.h
@@ -238,6 +238,7 @@
   bool VisitUsingDecl(UsingDecl *D);
   bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
   bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+  bool VisitStaticAssertDecl(StaticAssertDecl *D);
   
   // Name visitor
   bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
Index: cfe/trunk/tools/libclang/CIndex.cpp
===
--- cfe/trunk/tools/libclang/CIndex.cpp
+++ cfe/trunk/tools/libclang/CIndex.cpp
@@ -1230,6 +1230,14 @@
   return false;
 }
 
+bool CursorVisitor::VisitStaticAssertDecl(StaticAssertDecl *D) {
+  if (Visit(MakeCXCursor(D->getAssertExpr(), StmtParent, TU, RegionOfInterest)))
+return true;
+  if (Visit(MakeCXCursor(D->getMessage(), StmtParent, TU, RegionOfInterest)))
+return true;
+  return false;
+}
+
 bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
   switch 

r272273 - CIndex: add support for static_assert

2016-06-09 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Thu Jun  9 11:15:55 2016
New Revision: 272273

URL: http://llvm.org/viewvc/llvm-project?rev=272273=rev
Log:
CIndex: add support for static_assert

Differential Revision: http://reviews.llvm.org/D18080

Modified:
cfe/trunk/include/clang-c/Index.h
cfe/trunk/lib/Sema/SemaCodeComplete.cpp
cfe/trunk/tools/libclang/CIndex.cpp
cfe/trunk/tools/libclang/CursorVisitor.h

Modified: cfe/trunk/include/clang-c/Index.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=272273=272272=272273=diff
==
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Thu Jun  9 11:15:55 2016
@@ -2359,8 +2359,12 @@ enum CXCursorKind {
*/
   CXCursor_ModuleImportDecl  = 600,
   CXCursor_TypeAliasTemplateDecl = 601,
+  /**
+   * \brief A static_assert or _Static_assert node
+   */
+  CXCursor_StaticAssert  = 602,
   CXCursor_FirstExtraDecl= CXCursor_ModuleImportDecl,
-  CXCursor_LastExtraDecl = CXCursor_TypeAliasTemplateDecl,
+  CXCursor_LastExtraDecl = CXCursor_StaticAssert,
 
   /**
* \brief A code completion overload candidate.

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=272273=272272=272273=diff
==
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Thu Jun  9 11:15:55 2016
@@ -3044,6 +3044,7 @@ CXCursorKind clang::getCursorKindForDecl
 case Decl::ClassTemplatePartialSpecialization:
   return CXCursor_ClassTemplatePartialSpecialization;
 case Decl::UsingDirective: return CXCursor_UsingDirective;
+case Decl::StaticAssert:   return CXCursor_StaticAssert;
 case Decl::TranslationUnit:return CXCursor_TranslationUnit;
   
 case Decl::Using:

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=272273=272272=272273=diff
==
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Thu Jun  9 11:15:55 2016
@@ -1230,6 +1230,14 @@ bool CursorVisitor::VisitUnresolvedUsing
   return false;
 }
 
+bool CursorVisitor::VisitStaticAssertDecl(StaticAssertDecl *D) {
+  if (Visit(MakeCXCursor(D->getAssertExpr(), StmtParent, TU, 
RegionOfInterest)))
+return true;
+  if (Visit(MakeCXCursor(D->getMessage(), StmtParent, TU, RegionOfInterest)))
+return true;
+  return false;
+}
+
 bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
   switch (Name.getName().getNameKind()) {
   case clang::DeclarationName::Identifier:
@@ -4822,6 +4830,8 @@ CXString clang_getCursorKindSpelling(enu
   return cxstring::createRef("OverloadCandidate");
   case CXCursor_TypeAliasTemplateDecl:
   return cxstring::createRef("TypeAliasTemplateDecl");
+  case CXCursor_StaticAssert:
+  return cxstring::createRef("StaticAssert");
   }
 
   llvm_unreachable("Unhandled CXCursorKind");

Modified: cfe/trunk/tools/libclang/CursorVisitor.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CursorVisitor.h?rev=272273=272272=272273=diff
==
--- cfe/trunk/tools/libclang/CursorVisitor.h (original)
+++ cfe/trunk/tools/libclang/CursorVisitor.h Thu Jun  9 11:15:55 2016
@@ -238,6 +238,7 @@ public:
   bool VisitUsingDecl(UsingDecl *D);
   bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
   bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+  bool VisitStaticAssertDecl(StaticAssertDecl *D);
   
   // Name visitor
   bool VisitDeclarationNameInfo(DeclarationNameInfo Name);


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


r272274 - Make sizeof and alignof a CXCursor_UnaryExpr

2016-06-09 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Thu Jun  9 11:16:06 2016
New Revision: 272274

URL: http://llvm.org/viewvc/llvm-project?rev=272274=rev
Log:
Make sizeof and alignof a CXCursor_UnaryExpr

So we can match sizeof expressions more accurately than with UnexposedExpr

Differential Revision: http://reviews.llvm.org/D18081

Modified:
cfe/trunk/include/clang-c/Index.h
cfe/trunk/test/Index/annotate-tokens.c
cfe/trunk/tools/libclang/CXCursor.cpp

Modified: cfe/trunk/include/clang-c/Index.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=272274=272273=272274=diff
==
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Thu Jun  9 11:16:06 2016
@@ -1932,7 +1932,7 @@ enum CXCursorKind {
*/
   CXCursor_CXXDeleteExpr = 135,
 
-  /** \brief A unary expression.
+  /** \brief A unary expression. (noexcept, sizeof, or other traits)
*/
   CXCursor_UnaryExpr = 136,
 

Modified: cfe/trunk/test/Index/annotate-tokens.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/annotate-tokens.c?rev=272274=272273=272274=diff
==
--- cfe/trunk/test/Index/annotate-tokens.c (original)
+++ cfe/trunk/test/Index/annotate-tokens.c Thu Jun  9 11:16:06 2016
@@ -80,10 +80,10 @@ void test() {
 // CHECK: Punctuation: "(" [5:3 - 5:4] CStyleCastExpr=
 // CHECK: Keyword: "void" [5:4 - 5:8] CStyleCastExpr=
 // CHECK: Punctuation: ")" [5:8 - 5:9] CStyleCastExpr=
-// CHECK: Keyword: "sizeof" [5:9 - 5:15] UnexposedExpr=
-// CHECK: Punctuation: "(" [5:15 - 5:16] UnexposedExpr=
+// CHECK: Keyword: "sizeof" [5:9 - 5:15] UnaryExpr=
+// CHECK: Punctuation: "(" [5:15 - 5:16] UnaryExpr=
 // CHECK: Identifier: "T" [5:16 - 5:17] TypeRef=T:1:13
-// CHECK: Punctuation: ")" [5:17 - 5:18] UnexposedExpr=
+// CHECK: Punctuation: ")" [5:17 - 5:18] UnaryExpr=
 // CHECK: Punctuation: ";" [5:18 - 5:19] CompoundStmt=
 // CHECK: Keyword: "struct" [7:3 - 7:9] VarDecl=x:7:12 (Definition)
 // CHECK: Identifier: "X" [7:10 - 7:11] TypeRef=struct X:2:8

Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=272274=272273=272274=diff
==
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Thu Jun  9 11:16:06 2016
@@ -256,7 +256,6 @@ CXCursor cxcursor::MakeCXCursor(const St
   case Stmt::PredefinedExprClass:
   case Stmt::ShuffleVectorExprClass:
   case Stmt::ConvertVectorExprClass:
-  case Stmt::UnaryExprOrTypeTraitExprClass:
   case Stmt::VAArgExprClass:
   case Stmt::ObjCArrayLiteralClass:
   case Stmt::ObjCDictionaryLiteralClass:
@@ -327,6 +326,7 @@ CXCursor cxcursor::MakeCXCursor(const St
 K = CXCursor_UnaryOperator;
 break;
 
+  case Stmt::UnaryExprOrTypeTraitExprClass:
   case Stmt::CXXNoexceptExprClass:
 K = CXCursor_UnaryExpr;
 break;


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


[PATCH] D20821: Fix a few issues while skipping function bodies

2016-05-31 Thread Olivier Goffart via cfe-commits
ogoffart created this revision.
ogoffart added reviewers: cfe-commits, rsmith, akyrtzi.
Herald added a subscriber: klimek.

Fix a few issues while skipping function bodies

 - In functions with try { } catch { }, only the try block would be
   skipped, not the catch blocks

 - The template functions would still be parsed.

 - The initializers within a constructor would still be parsed.

 - The inline functions within class would still be stored, only to be
   discared later.

 - Invalid code with try would assert (as in "int foo() try assert_here")
   
This attempt to do even less while skipping function bodies. 


http://reviews.llvm.org/D20821

Files:
  lib/Parse/ParseCXXInlineMethods.cpp
  lib/Parse/ParseObjc.cpp
  lib/Parse/ParseStmt.cpp
  lib/Parse/Parser.cpp
  lib/Sema/SemaDecl.cpp
  unittests/Tooling/ToolingTest.cpp

Index: unittests/Tooling/ToolingTest.cpp
===
--- unittests/Tooling/ToolingTest.cpp
+++ unittests/Tooling/ToolingTest.cpp
@@ -241,7 +241,7 @@
 struct SkipBodyConsumer : public clang::ASTConsumer {
   /// Skip the 'skipMe' function.
   bool shouldSkipFunctionBody(Decl *D) override {
-FunctionDecl *F = dyn_cast(D);
+NamedDecl *F = dyn_cast(D);
 return F && F->getNameAsString() == "skipMe";
   }
 };
@@ -259,6 +259,36 @@
 "int skipMe() { an_error_here }"));
   EXPECT_FALSE(runToolOnCode(new SkipBodyAction,
  "int skipMeNot() { an_error_here }"));
+
+  // Test constructors with initializers
+  EXPECT_TRUE(runToolOnCode(new SkipBodyAction,
+"struct skipMe { skipMe() : an_error() { more error } };"));
+  EXPECT_TRUE(runToolOnCode(new SkipBodyAction,
+"struct skipMe { skipMe(); };"
+"skipMe::skipMe() : an_error() { more error }"));
+  EXPECT_FALSE(runToolOnCode(new SkipBodyAction,
+"struct skipMeNot { skipMeNot() : an_error() { } };"));
+  EXPECT_FALSE(runToolOnCode(new SkipBodyAction,
+"struct skipMeNot { skipMeNot(); };"
+"skipMeNot::skipMeNot() : an_error() { }"));
+
+  // Try/catch
+  EXPECT_TRUE(runToolOnCode(new SkipBodyAction,
+"void skipMe() try { an_error() } catch(error) { error };"));
+  EXPECT_TRUE(runToolOnCode(new SkipBodyAction,
+"struct S { void skipMe() try { an_error() } catch(error) { error } };"));
+  EXPECT_TRUE(runToolOnCode(new SkipBodyAction,
+"void skipMe() try { an_error() } catch(error) { error; }"
+"catch(error) { error } catch (error) { }"));
+  EXPECT_FALSE(runToolOnCode(new SkipBodyAction,
+"void skipMe() try something;")); // don't crash while parsing
+
+  // Template
+  EXPECT_TRUE(runToolOnCode(new SkipBodyAction,
+"template int skipMe() { an_error_here }"
+"int x = skipMe();"));
+  EXPECT_FALSE(runToolOnCode(new SkipBodyAction,
+"template int skipMeNot() { an_error_here }"));
 }
 
 TEST(runToolOnCodeWithArgs, TestNoDepFile) {
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -11378,7 +11378,7 @@
 FD->setHasSkippedBody();
   else if (ObjCMethodDecl *MD = dyn_cast_or_null(Decl))
 MD->setHasSkippedBody();
-  return ActOnFinishFunctionBody(Decl, nullptr);
+  return Decl;
 }
 
 Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
Index: lib/Parse/Parser.cpp
===
--- lib/Parse/Parser.cpp
+++ lib/Parse/Parser.cpp
@@ -1044,6 +1044,12 @@
 D.complete(DP);
 D.getMutableDeclSpec().abort();
 
+if (SkipFunctionBodies && (!DP || Actions.canSkipFunctionBody(DP)) &&
+trySkippingFunctionBody()) {
+  BodyScope.Exit();
+  return Actions.ActOnSkippedFunctionBody(DP);
+}
+
 CachedTokens Toks;
 LexTemplateFunctionForLateParsing(Toks);
 
@@ -1136,6 +1142,13 @@
 return Res;
   }
 
+  if (SkipFunctionBodies && (!Res || Actions.canSkipFunctionBody(Res)) &&
+  trySkippingFunctionBody()) {
+BodyScope.Exit();
+Actions.ActOnSkippedFunctionBody(Res);
+return Actions.ActOnFinishFunctionBody(Res, nullptr, false);
+  }
+
   if (Tok.is(tok::kw_try))
 return ParseFunctionTryBlock(Res, BodyScope);
 
Index: lib/Parse/ParseStmt.cpp
===
--- lib/Parse/ParseStmt.cpp
+++ lib/Parse/ParseStmt.cpp
@@ -1916,12 +1916,6 @@
   assert(Tok.is(tok::l_brace));
   SourceLocation LBraceLoc = Tok.getLocation();
 
-  if (SkipFunctionBodies && (!Decl || Actions.canSkipFunctionBody(Decl)) &&
-  trySkippingFunctionBody()) {
-BodyScope.Exit();
-return Actions.ActOnSkippedFunctionBody(Decl);
-  }
-
   PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc,
   "parsing function body");
 
@@ -1964,12 +1958,6 @@
   else
 Actions.ActOnDefaultCtorInitializers(Decl);
 
-  if (SkipFunctionBodies && Actions.canSkipFunctionBody(Decl) &&
-  

Re: [PATCH] D20511: Fix crash while parsing variable template with variadic template arguments

2016-05-26 Thread Olivier Goffart via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL270845: Fix crash while parsing variable template with 
variadic template arguments (authored by ogoffart).

Changed prior to commit:
  http://reviews.llvm.org/D20511?vs=58043=58595#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D20511

Files:
  cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
  cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp

Index: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
===
--- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
+++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
@@ -458,3 +458,9 @@
   template<> int g; // expected-error {{no variable template matches 
specialization; did you mean to use 'g' as function template instead?}}
 }
 
+#ifndef PRECXX11
+template  struct Variadic_t { };
+template  Variadic_t Variadic;
+auto variadic1 = Variadic<>;
+auto variadic2 = Variadic;
+#endif
Index: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
===
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
@@ -604,7 +604,7 @@
 //   Template argument deduction can extend the sequence of template 
 //   arguments corresponding to a template parameter pack, even when the
 //   sequence contains explicitly specified template arguments.
-if (!IsFunctionParameterPack) {
+if (!IsFunctionParameterPack && CurrentInstantiationScope) {
   if (NamedDecl *PartialPack 
 = 
CurrentInstantiationScope->getPartiallySubstitutedPack()){
 unsigned PartialDepth, PartialIndex;


Index: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
===
--- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
+++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
@@ -458,3 +458,9 @@
   template<> int g; // expected-error {{no variable template matches specialization; did you mean to use 'g' as function template instead?}}
 }
 
+#ifndef PRECXX11
+template  struct Variadic_t { };
+template  Variadic_t Variadic;
+auto variadic1 = Variadic<>;
+auto variadic2 = Variadic;
+#endif
Index: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
===
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
@@ -604,7 +604,7 @@
 //   Template argument deduction can extend the sequence of template 
 //   arguments corresponding to a template parameter pack, even when the
 //   sequence contains explicitly specified template arguments.
-if (!IsFunctionParameterPack) {
+if (!IsFunctionParameterPack && CurrentInstantiationScope) {
   if (NamedDecl *PartialPack 
 = CurrentInstantiationScope->getPartiallySubstitutedPack()){
 unsigned PartialDepth, PartialIndex;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r270845 - Fix crash while parsing variable template with variadic template arguments

2016-05-26 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Thu May 26 07:55:34 2016
New Revision: 270845

URL: http://llvm.org/viewvc/llvm-project?rev=270845=rev
Log:
Fix crash while parsing variable template with variadic template arguments

It is only a crash if the compiler optimize for this!=nullptr because
LocalInstantiationScope::getPartiallySubstitutedPack checks if 'this' is null
(This is crashing when clang is compiled with GCC6)

Differential Revision: http://reviews.llvm.org/D20511

Modified:
cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=270845=270844=270845=diff
==
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Thu May 26 07:55:34 2016
@@ -604,7 +604,7 @@ bool Sema::CheckParameterPacksForExpansi
 //   Template argument deduction can extend the sequence of template 
 //   arguments corresponding to a template parameter pack, even when the
 //   sequence contains explicitly specified template arguments.
-if (!IsFunctionParameterPack) {
+if (!IsFunctionParameterPack && CurrentInstantiationScope) {
   if (NamedDecl *PartialPack 
 = 
CurrentInstantiationScope->getPartiallySubstitutedPack()){
 unsigned PartialDepth, PartialIndex;

Modified: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp?rev=270845=270844=270845=diff
==
--- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp Thu May 26 
07:55:34 2016
@@ -458,3 +458,9 @@ namespace PR19169 {
   template<> int g; // expected-error {{no variable template matches 
specialization; did you mean to use 'g' as function template instead?}}
 }
 
+#ifndef PRECXX11
+template  struct Variadic_t { };
+template  Variadic_t Variadic;
+auto variadic1 = Variadic<>;
+auto variadic2 = Variadic;
+#endif


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


Re: [PATCH] D20821: Fix a few issues while skipping function bodies

2016-06-01 Thread Olivier Goffart via cfe-commits
ogoffart updated this revision to Diff 59197.
ogoffart added a comment.

Right, i forgot about the C++11 initializer list syntax.  I hope I got it right 
now.


http://reviews.llvm.org/D20821

Files:
  lib/Parse/ParseCXXInlineMethods.cpp
  lib/Parse/ParseObjc.cpp
  lib/Parse/ParseStmt.cpp
  lib/Parse/Parser.cpp
  lib/Sema/SemaDecl.cpp
  unittests/Tooling/ToolingTest.cpp

Index: unittests/Tooling/ToolingTest.cpp
===
--- unittests/Tooling/ToolingTest.cpp
+++ unittests/Tooling/ToolingTest.cpp
@@ -241,7 +241,7 @@
 struct SkipBodyConsumer : public clang::ASTConsumer {
   /// Skip the 'skipMe' function.
   bool shouldSkipFunctionBody(Decl *D) override {
-FunctionDecl *F = dyn_cast(D);
+NamedDecl *F = dyn_cast(D);
 return F && F->getNameAsString() == "skipMe";
   }
 };
@@ -259,6 +259,56 @@
 "int skipMe() { an_error_here }"));
   EXPECT_FALSE(runToolOnCode(new SkipBodyAction,
  "int skipMeNot() { an_error_here }"));
+
+  // Test constructors with initializers
+  EXPECT_TRUE(
+  runToolOnCode(new SkipBodyAction,
+"struct skipMe { skipMe() : an_error() { more error } };"));
+  EXPECT_TRUE(
+  runToolOnCode(new SkipBodyAction,
+"struct skipMe { skipMe(); };"
+"skipMe::skipMe() : an_error([](){;}) { more error }"));
+  EXPECT_TRUE(
+  runToolOnCode(new SkipBodyAction,
+"struct skipMe { skipMe(); };"
+"skipMe::skipMe() : an_error{[](){;}} { more error }"));
+  EXPECT_TRUE(
+  runToolOnCode(new SkipBodyAction,
+"struct skipMe { skipMe(); };"
+"skipMe::skipMe() : a>(), f{}, g() { error }"));
+  EXPECT_TRUE(
+  runToolOnCode(new SkipBodyAction,
+"struct skipMe { skipMe() : bases()... { error } };"));
+
+  EXPECT_FALSE(
+  runToolOnCode(new SkipBodyAction,
+"struct skipMeNot { skipMeNot() : an_error() { } };"));
+  EXPECT_FALSE(runToolOnCode(new SkipBodyAction,
+ "struct skipMeNot { skipMeNot(); };"
+ "skipMeNot::skipMeNot() : an_error() { }"));
+
+  // Try/catch
+  EXPECT_TRUE(runToolOnCode(
+  new SkipBodyAction,
+  "void skipMe() try { an_error() } catch(error) { error };"));
+  EXPECT_TRUE(runToolOnCode(
+  new SkipBodyAction,
+  "struct S { void skipMe() try { an_error() } catch(error) { error } };"));
+  EXPECT_TRUE(
+  runToolOnCode(new SkipBodyAction,
+"void skipMe() try { an_error() } catch(error) { error; }"
+"catch(error) { error } catch (error) { }"));
+  EXPECT_FALSE(runToolOnCode(
+  new SkipBodyAction,
+  "void skipMe() try something;")); // don't crash while parsing
+
+  // Template
+  EXPECT_TRUE(runToolOnCode(
+  new SkipBodyAction, "template int skipMe() { an_error_here }"
+  "int x = skipMe();"));
+  EXPECT_FALSE(
+  runToolOnCode(new SkipBodyAction,
+"template int skipMeNot() { an_error_here }"));
 }
 
 TEST(runToolOnCodeWithArgs, TestNoDepFile) {
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -11378,7 +11378,7 @@
 FD->setHasSkippedBody();
   else if (ObjCMethodDecl *MD = dyn_cast_or_null(Decl))
 MD->setHasSkippedBody();
-  return ActOnFinishFunctionBody(Decl, nullptr);
+  return Decl;
 }
 
 Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
Index: lib/Parse/Parser.cpp
===
--- lib/Parse/Parser.cpp
+++ lib/Parse/Parser.cpp
@@ -1044,6 +1044,12 @@
 D.complete(DP);
 D.getMutableDeclSpec().abort();
 
+if (SkipFunctionBodies && (!DP || Actions.canSkipFunctionBody(DP)) &&
+trySkippingFunctionBody()) {
+  BodyScope.Exit();
+  return Actions.ActOnSkippedFunctionBody(DP);
+}
+
 CachedTokens Toks;
 LexTemplateFunctionForLateParsing(Toks);
 
@@ -1136,6 +1142,13 @@
 return Res;
   }
 
+  if (SkipFunctionBodies && (!Res || Actions.canSkipFunctionBody(Res)) &&
+  trySkippingFunctionBody()) {
+BodyScope.Exit();
+Actions.ActOnSkippedFunctionBody(Res);
+return Actions.ActOnFinishFunctionBody(Res, nullptr, false);
+  }
+
   if (Tok.is(tok::kw_try))
 return ParseFunctionTryBlock(Res, BodyScope);
 
Index: lib/Parse/ParseStmt.cpp
===
--- lib/Parse/ParseStmt.cpp
+++ lib/Parse/ParseStmt.cpp
@@ -1916,12 +1916,6 @@
   assert(Tok.is(tok::l_brace));
   SourceLocation LBraceLoc = Tok.getLocation();
 
-  if (SkipFunctionBodies && (!Decl || Actions.canSkipFunctionBody(Decl)) &&
-  trySkippingFunctionBody()) {
-BodyScope.Exit();
-return Actions.ActOnSkippedFunctionBody(Decl);
-  }
-
   

Re: [PATCH] D20821: Fix a few issues while skipping function bodies

2016-06-16 Thread Olivier Goffart via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL272963: Fix a few issues while skipping function bodies 
(authored by ogoffart).

Changed prior to commit:
  http://reviews.llvm.org/D20821?vs=60340=61035#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D20821

Files:
  cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
  cfe/trunk/lib/Parse/ParseObjc.cpp
  cfe/trunk/lib/Parse/ParseStmt.cpp
  cfe/trunk/lib/Parse/Parser.cpp
  cfe/trunk/lib/Sema/SemaDecl.cpp
  cfe/trunk/test/CodeCompletion/ctor-initializer.cpp
  cfe/trunk/unittests/Tooling/ToolingTest.cpp

Index: cfe/trunk/test/CodeCompletion/ctor-initializer.cpp
===
--- cfe/trunk/test/CodeCompletion/ctor-initializer.cpp
+++ cfe/trunk/test/CodeCompletion/ctor-initializer.cpp
@@ -0,0 +1,41 @@
+struct Base1 {
+  Base1() : {}
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: COMPLETION: Pattern : member1(<#args#>)
+  // CHECK-CC1: COMPLETION: Pattern : member2(<#args#>
+
+  Base1(int) : member1(123), {}
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:7:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+  // CHECK-CC2-NOT: COMPLETION: Pattern : member1(<#args#>)
+  // CHECK-CC2: COMPLETION: Pattern : member2(<#args#>
+
+  int member1;
+  float member2;
+};
+
+struct Derived : public Base1 {
+  Derived();
+  Derived(int);
+  Derived(float);
+  int deriv1;
+};
+
+Derived::Derived() : {}
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: COMPLETION: Pattern : Base1(<#args#>)
+// CHECK-CC3: COMPLETION: Pattern : deriv1(<#args#>)
+
+Derived::Derived(int) try : {
+} catch (...) {
+}
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:28:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC4: COMPLETION: Pattern : Base1(<#args#>)
+// CHECK-CC4: COMPLETION: Pattern : deriv1(<#args#>)
+
+Derived::Derived(float) try : Base1(),
+{
+} catch (...) {
+}
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:35:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
+// CHECK-CC5-NOT: COMPLETION: Pattern : Base1(<#args#>)
+// CHECK-CC5: COMPLETION: Pattern : deriv1(<#args#>)
Index: cfe/trunk/lib/Sema/SemaDecl.cpp
===
--- cfe/trunk/lib/Sema/SemaDecl.cpp
+++ cfe/trunk/lib/Sema/SemaDecl.cpp
@@ -11384,7 +11384,7 @@
 FD->setHasSkippedBody();
   else if (ObjCMethodDecl *MD = dyn_cast_or_null(Decl))
 MD->setHasSkippedBody();
-  return ActOnFinishFunctionBody(Decl, nullptr);
+  return Decl;
 }
 
 Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
Index: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
===
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
@@ -101,6 +101,12 @@
 return FnD;
   }
 
+  if (SkipFunctionBodies && (!FnD || Actions.canSkipFunctionBody(FnD)) &&
+  trySkippingFunctionBody()) {
+Actions.ActOnSkippedFunctionBody(FnD);
+return FnD;
+  }
+
   // In delayed template parsing mode, if we are within a class template
   // or if we are about to parse function member template then consume
   // the tokens and store them for parsing at the end of the translation unit.
Index: cfe/trunk/lib/Parse/ParseObjc.cpp
===
--- cfe/trunk/lib/Parse/ParseObjc.cpp
+++ cfe/trunk/lib/Parse/ParseObjc.cpp
@@ -2656,6 +2656,12 @@
 /// StashAwayMethodOrFunctionBodyTokens -  Consume the tokens and store them 
 /// for later parsing.
 void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {
+  if (SkipFunctionBodies && (!MDecl || Actions.canSkipFunctionBody(MDecl)) &&
+  trySkippingFunctionBody()) {
+Actions.ActOnSkippedFunctionBody(MDecl);
+return;
+  }
+
   LexedMethod* LM = new LexedMethod(this, MDecl);
   CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM);
   CachedTokens  = LM->Toks;
Index: cfe/trunk/lib/Parse/Parser.cpp
===
--- cfe/trunk/lib/Parse/Parser.cpp
+++ cfe/trunk/lib/Parse/Parser.cpp
@@ -1044,6 +1044,12 @@
 D.complete(DP);
 D.getMutableDeclSpec().abort();
 
+if (SkipFunctionBodies && (!DP || Actions.canSkipFunctionBody(DP)) &&
+trySkippingFunctionBody()) {
+  BodyScope.Exit();
+  return Actions.ActOnSkippedFunctionBody(DP);
+}
+
 CachedTokens Toks;
 LexTemplateFunctionForLateParsing(Toks);
 
@@ -1136,6 +1142,13 @@
 return Res;
   }
 
+  if (SkipFunctionBodies && (!Res || Actions.canSkipFunctionBody(Res)) &&
+  trySkippingFunctionBody()) {
+BodyScope.Exit();
+Actions.ActOnSkippedFunctionBody(Res);
+return Actions.ActOnFinishFunctionBody(Res, nullptr, false);
+  }
+
   if (Tok.is(tok::kw_try))

Re: [PATCH] D19764: Keep invalid functions as part of the AST

2016-06-16 Thread Olivier Goffart via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL272962: Keep invalid functions as part of the AST (authored 
by ogoffart).

Changed prior to commit:
  http://reviews.llvm.org/D19764?vs=55714=61034#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D19764

Files:
  cfe/trunk/lib/Sema/SemaDecl.cpp
  cfe/trunk/test/Misc/ast-dump-invalid.cpp
  cfe/trunk/test/Sema/predefined-function.c

Index: cfe/trunk/test/Sema/predefined-function.c
===
--- cfe/trunk/test/Sema/predefined-function.c
+++ cfe/trunk/test/Sema/predefined-function.c
@@ -4,14 +4,13 @@
 enum Test {A=-1};
 char *funk(enum Test x);
 
-int eli(float b); // expected-note {{previous declaration is here}} \
-// expected-note{{passing argument to parameter 'b' here}}
+int eli(float b); // expected-note {{previous declaration is here}}
 int b(int c) {return 1;}
 
 int foo();
 int foo() {
   int eli(int (int)); // expected-error {{conflicting types for 'eli'}}
-  eli(b); // expected-error{{passing 'int (int)' to parameter of incompatible 
type 'float'}}
+  eli(b);
   return 0;
 }
 
Index: cfe/trunk/test/Misc/ast-dump-invalid.cpp
===
--- cfe/trunk/test/Misc/ast-dump-invalid.cpp
+++ cfe/trunk/test/Misc/ast-dump-invalid.cpp
@@ -41,3 +41,24 @@
 // CHECK-NEXT: `-ImplicitCastExpr {{.*}}  'int' 

 // CHECK-NEXT:   `-DeclRefExpr {{.*}}  'int' lvalue ParmVar 
{{.*}} 'i' 'int'
 
+
+namespace TestInvalidFunctionDecl {
+struct Str {
+   double foo1(double, invalid_type);
+};
+double Str::foo1(double, invalid_type)
+{ return 45; }
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl
+// CHECK-NEXT: |-CXXRecordDecl {{.*}}  line:46:8 struct 
Str definition
+// CHECK-NEXT: | |-CXXRecordDecl {{.*}}  col:8 implicit struct 
Str
+// CHECK-NEXT: | `-CXXMethodDecl {{.*}}  col:11 invalid 
foo1 'double (double, int)'
+// CHECK-NEXT: |   |-ParmVarDecl {{.*}}  col:22 'double'
+// CHECK-NEXT: |   `-ParmVarDecl {{.*}}  col:36 
invalid 'int'
+// CHECK-NEXT: `-CXXMethodDecl {{.*}} parent {{.*}}  
line:49:13 invalid foo1 'double (double, int)'
+// CHECK-NEXT:   |-ParmVarDecl {{.*}}  col:24 'double'
+// CHECK-NEXT:   |-ParmVarDecl {{.*}}  col:38 invalid 
'int'
+// CHECK-NEXT:   `-CompoundStmt {{.*}} 
+// CHECK-NEXT: `-ReturnStmt {{.*}} 
+// CHECK-NEXT:   `-ImplicitCastExpr {{.*}}  'double' 

+// CHECK-NEXT: `-IntegerLiteral {{.*}}  'int' 45
Index: cfe/trunk/lib/Sema/SemaDecl.cpp
===
--- cfe/trunk/lib/Sema/SemaDecl.cpp
+++ cfe/trunk/lib/Sema/SemaDecl.cpp
@@ -5100,10 +5100,9 @@
   if (!New)
 return nullptr;
 
-  // If this has an identifier and is not an invalid redeclaration or
-  // function template specialization, add it to the scope stack.
-  if (New->getDeclName() && AddToScope &&
-   !(D.isRedeclaration() && New->isInvalidDecl())) {
+  // If this has an identifier and is not a function template specialization,
+  // add it to the scope stack.
+  if (New->getDeclName() && AddToScope) {
 // Only make a locally-scoped extern declaration visible if it is the first
 // declaration of this entity. Qualified lookup for such an entity should
 // only find this declaration if there is no visible declaration of it.


Index: cfe/trunk/test/Sema/predefined-function.c
===
--- cfe/trunk/test/Sema/predefined-function.c
+++ cfe/trunk/test/Sema/predefined-function.c
@@ -4,14 +4,13 @@
 enum Test {A=-1};
 char *funk(enum Test x);
 
-int eli(float b); // expected-note {{previous declaration is here}} \
-// expected-note{{passing argument to parameter 'b' here}}
+int eli(float b); // expected-note {{previous declaration is here}}
 int b(int c) {return 1;}
 
 int foo();
 int foo() {
   int eli(int (int)); // expected-error {{conflicting types for 'eli'}}
-  eli(b); // expected-error{{passing 'int (int)' to parameter of incompatible type 'float'}}
+  eli(b);
   return 0;
 }
 
Index: cfe/trunk/test/Misc/ast-dump-invalid.cpp
===
--- cfe/trunk/test/Misc/ast-dump-invalid.cpp
+++ cfe/trunk/test/Misc/ast-dump-invalid.cpp
@@ -41,3 +41,24 @@
 // CHECK-NEXT: `-ImplicitCastExpr {{.*}}  'int' 
 // CHECK-NEXT:   `-DeclRefExpr {{.*}}  'int' lvalue ParmVar {{.*}} 'i' 'int'
 
+
+namespace TestInvalidFunctionDecl {
+struct Str {
+   double foo1(double, invalid_type);
+};
+double Str::foo1(double, invalid_type)
+{ return 45; }
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl
+// CHECK-NEXT: |-CXXRecordDecl {{.*}}  line:46:8 struct Str definition
+// CHECK-NEXT: | |-CXXRecordDecl {{.*}}  

r272963 - Fix a few issues while skipping function bodies

2016-06-16 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Thu Jun 16 16:40:06 2016
New Revision: 272963

URL: http://llvm.org/viewvc/llvm-project?rev=272963=rev
Log:
Fix a few issues while skipping function bodies

 - In functions with try { } catch { }, only the try block would be
   skipped, not the catch blocks

 - The template functions would still be parsed.

 - The initializers within a constructor would still be parsed.

 - The inline functions within class would still be stored, only to be
   discared later.

 - Invalid code with try would assert (as in "int foo() try assert_here")

This attempt to do even less while skipping function bodies.

Differential Revision: http://reviews.llvm.org/D20821

Added:
cfe/trunk/test/CodeCompletion/ctor-initializer.cpp
Modified:
cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
cfe/trunk/lib/Parse/ParseObjc.cpp
cfe/trunk/lib/Parse/ParseStmt.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/unittests/Tooling/ToolingTest.cpp

Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=272963=272962=272963=diff
==
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Thu Jun 16 16:40:06 2016
@@ -101,6 +101,12 @@ NamedDecl *Parser::ParseCXXInlineMethodD
 return FnD;
   }
 
+  if (SkipFunctionBodies && (!FnD || Actions.canSkipFunctionBody(FnD)) &&
+  trySkippingFunctionBody()) {
+Actions.ActOnSkippedFunctionBody(FnD);
+return FnD;
+  }
+
   // In delayed template parsing mode, if we are within a class template
   // or if we are about to parse function member template then consume
   // the tokens and store them for parsing at the end of the translation unit.

Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=272963=272962=272963=diff
==
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Thu Jun 16 16:40:06 2016
@@ -2656,6 +2656,12 @@ Parser::ParseObjCAutoreleasePoolStmt(Sou
 /// StashAwayMethodOrFunctionBodyTokens -  Consume the tokens and store them 
 /// for later parsing.
 void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {
+  if (SkipFunctionBodies && (!MDecl || Actions.canSkipFunctionBody(MDecl)) &&
+  trySkippingFunctionBody()) {
+Actions.ActOnSkippedFunctionBody(MDecl);
+return;
+  }
+
   LexedMethod* LM = new LexedMethod(this, MDecl);
   CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM);
   CachedTokens  = LM->Toks;

Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=272963=272962=272963=diff
==
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Thu Jun 16 16:40:06 2016
@@ -1916,12 +1916,6 @@ Decl *Parser::ParseFunctionStatementBody
   assert(Tok.is(tok::l_brace));
   SourceLocation LBraceLoc = Tok.getLocation();
 
-  if (SkipFunctionBodies && (!Decl || Actions.canSkipFunctionBody(Decl)) &&
-  trySkippingFunctionBody()) {
-BodyScope.Exit();
-return Actions.ActOnSkippedFunctionBody(Decl);
-  }
-
   PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc,
   "parsing function body");
 
@@ -1964,12 +1958,6 @@ Decl *Parser::ParseFunctionTryBlock(Decl
   else
 Actions.ActOnDefaultCtorInitializers(Decl);
 
-  if (SkipFunctionBodies && Actions.canSkipFunctionBody(Decl) &&
-  trySkippingFunctionBody()) {
-BodyScope.Exit();
-return Actions.ActOnSkippedFunctionBody(Decl);
-  }
-
   // Save and reset current vtordisp stack if we have entered a C++ method 
body.
   bool IsCXXMethod =
   getLangOpts().CPlusPlus && Decl && isa(Decl);
@@ -1990,27 +1978,43 @@ Decl *Parser::ParseFunctionTryBlock(Decl
 }
 
 bool Parser::trySkippingFunctionBody() {
-  assert(Tok.is(tok::l_brace));
   assert(SkipFunctionBodies &&
  "Should only be called when SkipFunctionBodies is enabled");
-
   if (!PP.isCodeCompletionEnabled()) {
-ConsumeBrace();
-SkipUntil(tok::r_brace);
+SkipFunctionBody();
 return true;
   }
 
   // We're in code-completion mode. Skip parsing for all function bodies unless
   // the body contains the code-completion point.
   TentativeParsingAction PA(*this);
-  ConsumeBrace();
-  if (SkipUntil(tok::r_brace, StopAtCodeCompletion)) {
+  bool IsTryCatch = Tok.is(tok::kw_try);
+  CachedTokens Toks;
+  bool ErrorInPrologue = ConsumeAndStoreFunctionPrologue(Toks);
+  if (llvm::any_of(Toks, [](const Token ) {
+return Tok.is(tok::code_completion);
+  })) {
+PA.Revert();
+return false;
+  }
+  if (ErrorInPrologue) {
 

r272961 - Functions declared in a scope should not hide previous declaration in earlier scopes

2016-06-16 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Thu Jun 16 16:39:46 2016
New Revision: 272961

URL: http://llvm.org/viewvc/llvm-project?rev=272961=rev
Log:
Functions declared in a scope should not hide previous declaration in earlier 
scopes

This code should be an error:

 void foo(int);
 void f3() {
   int foo(float);
   {
 float foo(int); // expected-error {{functions that differ only in their 
return type cannot be overloaded}}
   }
 }

the foo(float) function declared at function scope should not hide the 
float(int)
while trying to redeclare functions.

Differential Revision: http://reviews.llvm.org/D19763

Modified:
cfe/trunk/lib/Sema/SemaLookup.cpp
cfe/trunk/test/SemaCXX/function-redecl.cpp

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=272961=272960=272961=diff
==
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Jun 16 16:39:46 2016
@@ -1078,32 +1078,35 @@ bool Sema::CppLookupName(LookupResult 
 
   for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
 DeclContext *Ctx = S->getEntity();
-
+bool SearchNamespaceScope = true;
 // Check whether the IdResolver has anything in this scope.
-bool Found = false;
 for (; I != IEnd && S->isDeclScope(*I); ++I) {
   if (NamedDecl *ND = R.getAcceptableDecl(*I)) {
-if (NameKind == LookupRedeclarationWithLinkage) {
+if (NameKind == LookupRedeclarationWithLinkage &&
+!(*I)->isTemplateParameter()) {
+  // If it's a template parameter, we still find it, so we can diagnose
+  // the invalid redeclaration.
+
   // Determine whether this (or a previous) declaration is
   // out-of-scope.
   if (!LeftStartingScope && !Initial->isDeclScope(*I))
 LeftStartingScope = true;
 
   // If we found something outside of our starting scope that
-  // does not have linkage, skip it. If it's a template parameter,
-  // we still find it, so we can diagnose the invalid redeclaration.
-  if (LeftStartingScope && !((*I)->hasLinkage()) &&
-  !(*I)->isTemplateParameter()) {
+  // does not have linkage, skip it.
+  if (LeftStartingScope && !((*I)->hasLinkage())) {
 R.setShadowed();
 continue;
   }
+} else {
+  // We found something in this scope, we should not look at the
+  // namespace scope
+  SearchNamespaceScope = false;
 }
-
-Found = true;
 R.addDecl(ND);
   }
 }
-if (Found) {
+if (!SearchNamespaceScope) {
   R.resolveKind();
   if (S->isClassScope())
 if (CXXRecordDecl *Record = dyn_cast_or_null(Ctx))

Modified: cfe/trunk/test/SemaCXX/function-redecl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/function-redecl.cpp?rev=272961=272960=272961=diff
==
--- cfe/trunk/test/SemaCXX/function-redecl.cpp (original)
+++ cfe/trunk/test/SemaCXX/function-redecl.cpp Thu Jun 16 16:39:46 2016
@@ -7,7 +7,7 @@ namespace N {
 void bar(int); // expected-note 2{{previous declaration is here}}
   }
 
-  void foo(int); // expected-note 2{{previous declaration is here}}
+  void foo(int); // expected-note 3{{previous declaration is here}}
 
   void f2() {
 int foo(int); // expected-error {{functions that differ only in their 
return type cannot be overloaded}}
@@ -25,6 +25,13 @@ namespace N {
   }
 }
   }
+
+  void f3() {
+int foo(float);
+{
+  float foo(int); // expected-error {{functions that differ only in their 
return type cannot be overloaded}}
+}
+  }
 }
 
 class A {


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


Re: [PATCH] D19763: Functions declared in a scope should not hide previous declaration in earlier scopes

2016-06-16 Thread Olivier Goffart via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL272961: Functions declared in a scope should not hide 
previous declaration in earlier… (authored by ogoffart).

Changed prior to commit:
  http://reviews.llvm.org/D19763?vs=55712=61033#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D19763

Files:
  cfe/trunk/lib/Sema/SemaLookup.cpp
  cfe/trunk/test/SemaCXX/function-redecl.cpp

Index: cfe/trunk/test/SemaCXX/function-redecl.cpp
===
--- cfe/trunk/test/SemaCXX/function-redecl.cpp
+++ cfe/trunk/test/SemaCXX/function-redecl.cpp
@@ -7,7 +7,7 @@
 void bar(int); // expected-note 2{{previous declaration is here}}
   }
 
-  void foo(int); // expected-note 2{{previous declaration is here}}
+  void foo(int); // expected-note 3{{previous declaration is here}}
 
   void f2() {
 int foo(int); // expected-error {{functions that differ only in their 
return type cannot be overloaded}}
@@ -25,6 +25,13 @@
   }
 }
   }
+
+  void f3() {
+int foo(float);
+{
+  float foo(int); // expected-error {{functions that differ only in their 
return type cannot be overloaded}}
+}
+  }
 }
 
 class A {
Index: cfe/trunk/lib/Sema/SemaLookup.cpp
===
--- cfe/trunk/lib/Sema/SemaLookup.cpp
+++ cfe/trunk/lib/Sema/SemaLookup.cpp
@@ -1078,32 +1078,35 @@
 
   for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
 DeclContext *Ctx = S->getEntity();
-
+bool SearchNamespaceScope = true;
 // Check whether the IdResolver has anything in this scope.
-bool Found = false;
 for (; I != IEnd && S->isDeclScope(*I); ++I) {
   if (NamedDecl *ND = R.getAcceptableDecl(*I)) {
-if (NameKind == LookupRedeclarationWithLinkage) {
+if (NameKind == LookupRedeclarationWithLinkage &&
+!(*I)->isTemplateParameter()) {
+  // If it's a template parameter, we still find it, so we can diagnose
+  // the invalid redeclaration.
+
   // Determine whether this (or a previous) declaration is
   // out-of-scope.
   if (!LeftStartingScope && !Initial->isDeclScope(*I))
 LeftStartingScope = true;
 
   // If we found something outside of our starting scope that
-  // does not have linkage, skip it. If it's a template parameter,
-  // we still find it, so we can diagnose the invalid redeclaration.
-  if (LeftStartingScope && !((*I)->hasLinkage()) &&
-  !(*I)->isTemplateParameter()) {
+  // does not have linkage, skip it.
+  if (LeftStartingScope && !((*I)->hasLinkage())) {
 R.setShadowed();
 continue;
   }
+} else {
+  // We found something in this scope, we should not look at the
+  // namespace scope
+  SearchNamespaceScope = false;
 }
-
-Found = true;
 R.addDecl(ND);
   }
 }
-if (Found) {
+if (!SearchNamespaceScope) {
   R.resolveKind();
   if (S->isClassScope())
 if (CXXRecordDecl *Record = dyn_cast_or_null(Ctx))


Index: cfe/trunk/test/SemaCXX/function-redecl.cpp
===
--- cfe/trunk/test/SemaCXX/function-redecl.cpp
+++ cfe/trunk/test/SemaCXX/function-redecl.cpp
@@ -7,7 +7,7 @@
 void bar(int); // expected-note 2{{previous declaration is here}}
   }
 
-  void foo(int); // expected-note 2{{previous declaration is here}}
+  void foo(int); // expected-note 3{{previous declaration is here}}
 
   void f2() {
 int foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}}
@@ -25,6 +25,13 @@
   }
 }
   }
+
+  void f3() {
+int foo(float);
+{
+  float foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}}
+}
+  }
 }
 
 class A {
Index: cfe/trunk/lib/Sema/SemaLookup.cpp
===
--- cfe/trunk/lib/Sema/SemaLookup.cpp
+++ cfe/trunk/lib/Sema/SemaLookup.cpp
@@ -1078,32 +1078,35 @@
 
   for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
 DeclContext *Ctx = S->getEntity();
-
+bool SearchNamespaceScope = true;
 // Check whether the IdResolver has anything in this scope.
-bool Found = false;
 for (; I != IEnd && S->isDeclScope(*I); ++I) {
   if (NamedDecl *ND = R.getAcceptableDecl(*I)) {
-if (NameKind == LookupRedeclarationWithLinkage) {
+if (NameKind == LookupRedeclarationWithLinkage &&
+!(*I)->isTemplateParameter()) {
+  // If it's a template parameter, we still find it, so we can diagnose
+  // the invalid redeclaration.
+
   // Determine whether this (or a previous) declaration is
   // out-of-scope.
   if (!LeftStartingScope && 

r272962 - Keep invalid functions as part of the AST

2016-06-16 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Thu Jun 16 16:39:55 2016
New Revision: 272962

URL: http://llvm.org/viewvc/llvm-project?rev=272962=rev
Log:
Keep invalid functions as part of the AST

Differential Revision: http://reviews.llvm.org/D19764

Modified:
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/Misc/ast-dump-invalid.cpp
cfe/trunk/test/Sema/predefined-function.c

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=272962=272961=272962=diff
==
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jun 16 16:39:55 2016
@@ -5100,10 +5100,9 @@ NamedDecl *Sema::HandleDeclarator(Scope
   if (!New)
 return nullptr;
 
-  // If this has an identifier and is not an invalid redeclaration or
-  // function template specialization, add it to the scope stack.
-  if (New->getDeclName() && AddToScope &&
-   !(D.isRedeclaration() && New->isInvalidDecl())) {
+  // If this has an identifier and is not a function template specialization,
+  // add it to the scope stack.
+  if (New->getDeclName() && AddToScope) {
 // Only make a locally-scoped extern declaration visible if it is the first
 // declaration of this entity. Qualified lookup for such an entity should
 // only find this declaration if there is no visible declaration of it.

Modified: cfe/trunk/test/Misc/ast-dump-invalid.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-invalid.cpp?rev=272962=272961=272962=diff
==
--- cfe/trunk/test/Misc/ast-dump-invalid.cpp (original)
+++ cfe/trunk/test/Misc/ast-dump-invalid.cpp Thu Jun 16 16:39:55 2016
@@ -41,3 +41,24 @@ int g(int i) {
 // CHECK-NEXT: `-ImplicitCastExpr {{.*}}  'int' 

 // CHECK-NEXT:   `-DeclRefExpr {{.*}}  'int' lvalue ParmVar 
{{.*}} 'i' 'int'
 
+
+namespace TestInvalidFunctionDecl {
+struct Str {
+   double foo1(double, invalid_type);
+};
+double Str::foo1(double, invalid_type)
+{ return 45; }
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl
+// CHECK-NEXT: |-CXXRecordDecl {{.*}}  line:46:8 struct 
Str definition
+// CHECK-NEXT: | |-CXXRecordDecl {{.*}}  col:8 implicit struct 
Str
+// CHECK-NEXT: | `-CXXMethodDecl {{.*}}  col:11 invalid 
foo1 'double (double, int)'
+// CHECK-NEXT: |   |-ParmVarDecl {{.*}}  col:22 'double'
+// CHECK-NEXT: |   `-ParmVarDecl {{.*}}  col:36 
invalid 'int'
+// CHECK-NEXT: `-CXXMethodDecl {{.*}} parent {{.*}}  
line:49:13 invalid foo1 'double (double, int)'
+// CHECK-NEXT:   |-ParmVarDecl {{.*}}  col:24 'double'
+// CHECK-NEXT:   |-ParmVarDecl {{.*}}  col:38 invalid 
'int'
+// CHECK-NEXT:   `-CompoundStmt {{.*}} 
+// CHECK-NEXT: `-ReturnStmt {{.*}} 
+// CHECK-NEXT:   `-ImplicitCastExpr {{.*}}  'double' 

+// CHECK-NEXT: `-IntegerLiteral {{.*}}  'int' 45

Modified: cfe/trunk/test/Sema/predefined-function.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/predefined-function.c?rev=272962=272961=272962=diff
==
--- cfe/trunk/test/Sema/predefined-function.c (original)
+++ cfe/trunk/test/Sema/predefined-function.c Thu Jun 16 16:39:55 2016
@@ -4,14 +4,13 @@ char *funk(int format);
 enum Test {A=-1};
 char *funk(enum Test x);
 
-int eli(float b); // expected-note {{previous declaration is here}} \
-// expected-note{{passing argument to parameter 'b' here}}
+int eli(float b); // expected-note {{previous declaration is here}}
 int b(int c) {return 1;}
 
 int foo();
 int foo() {
   int eli(int (int)); // expected-error {{conflicting types for 'eli'}}
-  eli(b); // expected-error{{passing 'int (int)' to parameter of incompatible 
type 'float'}}
+  eli(b);
   return 0;
 }
 


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


Re: [PATCH] D19327: Keep invalid function body as part of the AST

2016-06-16 Thread Olivier Goffart via cfe-commits
ogoffart abandoned this revision.
ogoffart added a comment.

Replaced by http://reviews.llvm.org/D19764


http://reviews.llvm.org/D19327



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


Re: [PATCH] D21497: Fix test to specify C++03 (fails with C++11).

2016-06-19 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

I'm sorry for commiting broken test.

However this is supposed to work also in C++11 mode.  I'm investigating what's 
wrong.


http://reviews.llvm.org/D21497



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


Re: [PATCH] D21497: Fix test to specify C++03 (fails with C++11).

2016-06-19 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

I made http://reviews.llvm.org/D21502 that should also fix this test.


http://reviews.llvm.org/D21497



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


Re: [PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11

2016-06-28 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

Ping.

The problem i'm fixing here is how we recover invalid code in the ctor-init 
part as we skip the function body. 
In particular, we want to know if the '{' is the begining of the body or not. 
In C++03, we always consider it as the beginng of the body.  The problem was 
that in C++11 we don't, making the code skip too much, causing worse parse 
error later.

So what this patch is doing is finding heuristics to know if the '{' is 
starting a function body or not.
The rules are the following:  If we are not in a template argument, anf that 
the previous tokens are not an identifier, or a > , then it is much more likely 
to be the function body.  We verify that further by checking that the token 
after the matching '}'

I also changed the code to just ignore the code_completion token at this point. 
The previous code was making it thinking that it would then be a template 
argument. But this is not likely.


http://reviews.llvm.org/D21502



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


Re: [PATCH] D16973: Fix ICE with constexpr and friend functions

2016-02-07 Thread Olivier Goffart via cfe-commits
ogoffart updated this revision to Diff 47146.
ogoffart added a comment.

Optimized by avoiding repeated call to getBody


http://reviews.llvm.org/D16973

Files:
  lib/AST/ExprConstant.cpp
  test/SemaCXX/constant-expression-cxx11.cpp

Index: test/SemaCXX/constant-expression-cxx11.cpp
===
--- test/SemaCXX/constant-expression-cxx11.cpp
+++ test/SemaCXX/constant-expression-cxx11.cpp
@@ -2005,3 +2005,13 @@
   constexpr int a = *f().p;
   constexpr int b = *g().p;
 }
+
+namespace IncompleteClass {
+  struct XX {
+static constexpr int f(XX*) { return 1; } // expected-note {{here}}
+friend constexpr int g(XX*) { return 2; } // expected-note {{here}}
+
+static constexpr int i = f(static_cast(nullptr)); // expected-error 
{{constexpr variable 'i' must be initialized by a constant expression}}  
expected-note {{undefined function 'f' cannot be used in a constant expression}}
+static constexpr int j = g(static_cast(nullptr)); // expected-error 
{{constexpr variable 'j' must be initialized by a constant expression}}  
expected-note {{undefined function 'g' cannot be used in a constant expression}}
+  };
+}
Index: lib/AST/ExprConstant.cpp
===
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -3736,7 +3736,8 @@
 /// expression.
 static bool CheckConstexprFunction(EvalInfo , SourceLocation CallLoc,
const FunctionDecl *Declaration,
-   const FunctionDecl *Definition) {
+   const FunctionDecl *Definition,
+   const Stmt *Body) {
   // Potential constant expressions can contain calls to declared, but not yet
   // defined, constexpr functions.
   if (Info.checkingPotentialConstantExpression() && !Definition &&
@@ -3749,7 +3750,8 @@
 return false;
 
   // Can we evaluate this function call?
-  if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl())
+  if (Definition && Definition->isConstexpr() &&
+  !Definition->isInvalidDecl() && Body)
 return true;
 
   if (Info.getLangOpts().CPlusPlus11) {
@@ -4275,7 +4277,7 @@
 const FunctionDecl *Definition = nullptr;
 Stmt *Body = FD->getBody(Definition);
 
-if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition) ||
+if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) ||
 !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, 
Info,
 Result, ResultSlot))
   return false;
@@ -5483,9 +5485,9 @@
   }
 
   const FunctionDecl *Definition = nullptr;
-  FD->getBody(Definition);
+  auto Body = FD->getBody(Definition);
 
-  if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition))
+  if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body))
 return false;
 
   // Avoid materializing a temporary for an elidable copy/move constructor.
@@ -5971,9 +5973,9 @@
   }
 
   const FunctionDecl *Definition = nullptr;
-  FD->getBody(Definition);
+  auto Body = FD->getBody(Definition);
 
-  if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition))
+  if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body))
 return false;
 
   if (ZeroInit && !HadZeroInit) {


Index: test/SemaCXX/constant-expression-cxx11.cpp
===
--- test/SemaCXX/constant-expression-cxx11.cpp
+++ test/SemaCXX/constant-expression-cxx11.cpp
@@ -2005,3 +2005,13 @@
   constexpr int a = *f().p;
   constexpr int b = *g().p;
 }
+
+namespace IncompleteClass {
+  struct XX {
+static constexpr int f(XX*) { return 1; } // expected-note {{here}}
+friend constexpr int g(XX*) { return 2; } // expected-note {{here}}
+
+static constexpr int i = f(static_cast(nullptr)); // expected-error {{constexpr variable 'i' must be initialized by a constant expression}}  expected-note {{undefined function 'f' cannot be used in a constant expression}}
+static constexpr int j = g(static_cast(nullptr)); // expected-error {{constexpr variable 'j' must be initialized by a constant expression}}  expected-note {{undefined function 'g' cannot be used in a constant expression}}
+  };
+}
Index: lib/AST/ExprConstant.cpp
===
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -3736,7 +3736,8 @@
 /// expression.
 static bool CheckConstexprFunction(EvalInfo , SourceLocation CallLoc,
const FunctionDecl *Declaration,
-   const FunctionDecl *Definition) {
+   const FunctionDecl *Definition,
+   const Stmt *Body) {
   // Potential constant expressions can contain calls to declared, but not yet
   // defined, 

[PATCH] D16973: Fix ICE with constexpr and friend functions

2016-02-07 Thread Olivier Goffart via cfe-commits
ogoffart created this revision.
ogoffart added reviewers: rsmith, cfe-commits.

Fix a crash while parsing this code:

  struct X  {
friend constexpr int foo(X*) { return 12; }
static constexpr int j = foo(static_cast(nullptr));
  };

I also added a test for the static function case because i don't think this was 
tested before.




http://reviews.llvm.org/D16973

Files:
  lib/AST/ExprConstant.cpp
  test/SemaCXX/constant-expression-cxx11.cpp

Index: test/SemaCXX/constant-expression-cxx11.cpp
===
--- test/SemaCXX/constant-expression-cxx11.cpp
+++ test/SemaCXX/constant-expression-cxx11.cpp
@@ -2005,3 +2005,13 @@
   constexpr int a = *f().p;
   constexpr int b = *g().p;
 }
+
+namespace IncompleteClass {
+  struct XX {
+static constexpr int f(XX*) { return 1; } // expected-note {{here}}
+friend constexpr int g(XX*) { return 2; } // expected-note {{here}}
+
+static constexpr int i = f(static_cast(nullptr)); // expected-error 
{{constexpr variable 'i' must be initialized by a constant expression}}  
expected-note {{undefined function 'f' cannot be used in a constant expression}}
+static constexpr int j = g(static_cast(nullptr)); // expected-error 
{{constexpr variable 'j' must be initialized by a constant expression}}  
expected-note {{undefined function 'g' cannot be used in a constant expression}}
+  };
+}
\ No newline at end of file
Index: lib/AST/ExprConstant.cpp
===
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -3749,7 +3749,8 @@
 return false;
 
   // Can we evaluate this function call?
-  if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl())
+  if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl()
+  && Definition->getBody())
 return true;
 
   if (Info.getLangOpts().CPlusPlus11) {


Index: test/SemaCXX/constant-expression-cxx11.cpp
===
--- test/SemaCXX/constant-expression-cxx11.cpp
+++ test/SemaCXX/constant-expression-cxx11.cpp
@@ -2005,3 +2005,13 @@
   constexpr int a = *f().p;
   constexpr int b = *g().p;
 }
+
+namespace IncompleteClass {
+  struct XX {
+static constexpr int f(XX*) { return 1; } // expected-note {{here}}
+friend constexpr int g(XX*) { return 2; } // expected-note {{here}}
+
+static constexpr int i = f(static_cast(nullptr)); // expected-error {{constexpr variable 'i' must be initialized by a constant expression}}  expected-note {{undefined function 'f' cannot be used in a constant expression}}
+static constexpr int j = g(static_cast(nullptr)); // expected-error {{constexpr variable 'j' must be initialized by a constant expression}}  expected-note {{undefined function 'g' cannot be used in a constant expression}}
+  };
+}
\ No newline at end of file
Index: lib/AST/ExprConstant.cpp
===
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -3749,7 +3749,8 @@
 return false;
 
   // Can we evaluate this function call?
-  if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl())
+  if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl()
+  && Definition->getBody())
 return true;
 
   if (Info.getLangOpts().CPlusPlus11) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D16973: Fix ICE with constexpr and friend functions

2016-02-12 Thread Olivier Goffart via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL260675: Fix ICE with constexpr and friend functions 
(authored by ogoffart).

Changed prior to commit:
  http://reviews.llvm.org/D16973?vs=47146=47791#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D16973

Files:
  cfe/trunk/lib/AST/ExprConstant.cpp
  cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp

Index: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
===
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
@@ -2005,3 +2005,13 @@
   constexpr int a = *f().p;
   constexpr int b = *g().p;
 }
+
+namespace IncompleteClass {
+  struct XX {
+static constexpr int f(XX*) { return 1; } // expected-note {{here}}
+friend constexpr int g(XX*) { return 2; } // expected-note {{here}}
+
+static constexpr int i = f(static_cast(nullptr)); // expected-error 
{{constexpr variable 'i' must be initialized by a constant expression}}  
expected-note {{undefined function 'f' cannot be used in a constant expression}}
+static constexpr int j = g(static_cast(nullptr)); // expected-error 
{{constexpr variable 'j' must be initialized by a constant expression}}  
expected-note {{undefined function 'g' cannot be used in a constant expression}}
+  };
+}
Index: cfe/trunk/lib/AST/ExprConstant.cpp
===
--- cfe/trunk/lib/AST/ExprConstant.cpp
+++ cfe/trunk/lib/AST/ExprConstant.cpp
@@ -3736,7 +3736,8 @@
 /// expression.
 static bool CheckConstexprFunction(EvalInfo , SourceLocation CallLoc,
const FunctionDecl *Declaration,
-   const FunctionDecl *Definition) {
+   const FunctionDecl *Definition,
+   const Stmt *Body) {
   // Potential constant expressions can contain calls to declared, but not yet
   // defined, constexpr functions.
   if (Info.checkingPotentialConstantExpression() && !Definition &&
@@ -3749,7 +3750,8 @@
 return false;
 
   // Can we evaluate this function call?
-  if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl())
+  if (Definition && Definition->isConstexpr() &&
+  !Definition->isInvalidDecl() && Body)
 return true;
 
   if (Info.getLangOpts().CPlusPlus11) {
@@ -4275,7 +4277,7 @@
 const FunctionDecl *Definition = nullptr;
 Stmt *Body = FD->getBody(Definition);
 
-if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition) ||
+if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) ||
 !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, 
Info,
 Result, ResultSlot))
   return false;
@@ -5483,9 +5485,9 @@
   }
 
   const FunctionDecl *Definition = nullptr;
-  FD->getBody(Definition);
+  auto Body = FD->getBody(Definition);
 
-  if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition))
+  if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body))
 return false;
 
   // Avoid materializing a temporary for an elidable copy/move constructor.
@@ -5971,9 +5973,9 @@
   }
 
   const FunctionDecl *Definition = nullptr;
-  FD->getBody(Definition);
+  auto Body = FD->getBody(Definition);
 
-  if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition))
+  if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body))
 return false;
 
   if (ZeroInit && !HadZeroInit) {


Index: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
===
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
@@ -2005,3 +2005,13 @@
   constexpr int a = *f().p;
   constexpr int b = *g().p;
 }
+
+namespace IncompleteClass {
+  struct XX {
+static constexpr int f(XX*) { return 1; } // expected-note {{here}}
+friend constexpr int g(XX*) { return 2; } // expected-note {{here}}
+
+static constexpr int i = f(static_cast(nullptr)); // expected-error {{constexpr variable 'i' must be initialized by a constant expression}}  expected-note {{undefined function 'f' cannot be used in a constant expression}}
+static constexpr int j = g(static_cast(nullptr)); // expected-error {{constexpr variable 'j' must be initialized by a constant expression}}  expected-note {{undefined function 'g' cannot be used in a constant expression}}
+  };
+}
Index: cfe/trunk/lib/AST/ExprConstant.cpp
===
--- cfe/trunk/lib/AST/ExprConstant.cpp
+++ cfe/trunk/lib/AST/ExprConstant.cpp
@@ -3736,7 +3736,8 @@
 /// expression.
 static bool CheckConstexprFunction(EvalInfo , SourceLocation CallLoc,
const FunctionDecl *Declaration,
-   

r260675 - Fix ICE with constexpr and friend functions

2016-02-12 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Fri Feb 12 06:34:44 2016
New Revision: 260675

URL: http://llvm.org/viewvc/llvm-project?rev=260675=rev
Log:
Fix ICE with constexpr and friend functions

Fix a crash while parsing this code:

  struct X  {
friend constexpr int foo(X*) { return 12; }
static constexpr int j = foo(static_cast(nullptr));
  };

Differential Revision: http://reviews.llvm.org/D16973

Modified:
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=260675=260674=260675=diff
==
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Feb 12 06:34:44 2016
@@ -3736,7 +3736,8 @@ static bool CheckTrivialDefaultConstruct
 /// expression.
 static bool CheckConstexprFunction(EvalInfo , SourceLocation CallLoc,
const FunctionDecl *Declaration,
-   const FunctionDecl *Definition) {
+   const FunctionDecl *Definition,
+   const Stmt *Body) {
   // Potential constant expressions can contain calls to declared, but not yet
   // defined, constexpr functions.
   if (Info.checkingPotentialConstantExpression() && !Definition &&
@@ -3749,7 +3750,8 @@ static bool CheckConstexprFunction(EvalI
 return false;
 
   // Can we evaluate this function call?
-  if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl())
+  if (Definition && Definition->isConstexpr() &&
+  !Definition->isInvalidDecl() && Body)
 return true;
 
   if (Info.getLangOpts().CPlusPlus11) {
@@ -4275,7 +4277,7 @@ public:
 const FunctionDecl *Definition = nullptr;
 Stmt *Body = FD->getBody(Definition);
 
-if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition) ||
+if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) ||
 !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, 
Info,
 Result, ResultSlot))
   return false;
@@ -5483,9 +5485,9 @@ bool RecordExprEvaluator::VisitCXXConstr
   }
 
   const FunctionDecl *Definition = nullptr;
-  FD->getBody(Definition);
+  auto Body = FD->getBody(Definition);
 
-  if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition))
+  if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body))
 return false;
 
   // Avoid materializing a temporary for an elidable copy/move constructor.
@@ -5971,9 +5973,9 @@ bool ArrayExprEvaluator::VisitCXXConstru
   }
 
   const FunctionDecl *Definition = nullptr;
-  FD->getBody(Definition);
+  auto Body = FD->getBody(Definition);
 
-  if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition))
+  if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body))
 return false;
 
   if (ZeroInit && !HadZeroInit) {

Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=260675=260674=260675=diff
==
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Fri Feb 12 06:34:44 
2016
@@ -2005,3 +2005,13 @@ namespace PR24597 {
   constexpr int a = *f().p;
   constexpr int b = *g().p;
 }
+
+namespace IncompleteClass {
+  struct XX {
+static constexpr int f(XX*) { return 1; } // expected-note {{here}}
+friend constexpr int g(XX*) { return 2; } // expected-note {{here}}
+
+static constexpr int i = f(static_cast(nullptr)); // expected-error 
{{constexpr variable 'i' must be initialized by a constant expression}}  
expected-note {{undefined function 'f' cannot be used in a constant expression}}
+static constexpr int j = g(static_cast(nullptr)); // expected-error 
{{constexpr variable 'j' must be initialized by a constant expression}}  
expected-note {{undefined function 'g' cannot be used in a constant expression}}
+  };
+}


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


Re: [PATCH] D16973: Fix ICE with constexpr and friend functions

2016-02-11 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

ping?


http://reviews.llvm.org/D16973



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


r263639 - Fix destructor definition of invalid classes

2016-03-19 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Wed Mar 16 09:36:11 2016
New Revision: 263639

URL: http://llvm.org/viewvc/llvm-project?rev=263639=rev
Log:
Fix destructor definition of invalid classes

The declaration of the destructor of an invalid class was not properly marked
as noexcept. As a result, the definition of the same destructor, which was
properly implicitly marked as noexcept, would not match the definition.
This would cause the definition CXXDestructorDecl to be matked as invalid
and omited from the AST.

Differential Revision: http://reviews.llvm.org/D17988

Modified:
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/SemaCXX/destructor.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=263639=263638=263639=diff
==
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Mar 16 09:36:11 2016
@@ -13862,15 +13862,17 @@ void Sema::ActOnFields(Scope *S, SourceL
I = CXXRecord->conversion_begin(),
E = CXXRecord->conversion_end(); I != E; ++I)
   I.setAccess((*I)->getAccess());
-
-if (!CXXRecord->isDependentType()) {
-  if (CXXRecord->hasUserDeclaredDestructor()) {
-// Adjust user-defined destructor exception spec.
-if (getLangOpts().CPlusPlus11)
-  AdjustDestructorExceptionSpec(CXXRecord,
-CXXRecord->getDestructor());
-  }
+  }
 
+  if (!CXXRecord->isDependentType()) {
+if (CXXRecord->hasUserDeclaredDestructor()) {
+  // Adjust user-defined destructor exception spec.
+  if (getLangOpts().CPlusPlus11)
+AdjustDestructorExceptionSpec(CXXRecord,
+  CXXRecord->getDestructor());
+}
+
+if (!CXXRecord->isInvalidDecl()) {
   // Add any implicitly-declared members to this class.
   AddImplicitlyDeclaredMembersToClass(CXXRecord);
 

Modified: cfe/trunk/test/SemaCXX/destructor.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/destructor.cpp?rev=263639=263638=263639=diff
==
--- cfe/trunk/test/SemaCXX/destructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/destructor.cpp Wed Mar 16 09:36:11 2016
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only 
-Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
+// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only 
-Wnon-virtual-dtor -Wdelete-non-virtual-dtor -fcxx-exceptions -verify %s
 // RUN: %clang_cc1 -std=c++11 -triple %ms_abi_triple -DMSABI -fsyntax-only 
-Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
 class A {
 public:
@@ -423,3 +423,11 @@ void g(S s) {
   (s.~S); // expected-error{{reference to destructor must be called}}
 }
 }
+
+class Invalid {
+~Invalid();
+UnknownType xx; // expected-error{{unknown type name}}
+};
+
+// The constructor definition should not have errors
+Invalid::~Invalid() {}


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


Re: [PATCH] D17988: Fix destructor definition of invalid classes

2016-03-19 Thread Olivier Goffart via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL263639: Fix destructor definition of invalid classes 
(authored by ogoffart).

Changed prior to commit:
  http://reviews.llvm.org/D17988?vs=50124=50822#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D17988

Files:
  cfe/trunk/lib/Sema/SemaDecl.cpp
  cfe/trunk/test/SemaCXX/destructor.cpp

Index: cfe/trunk/test/SemaCXX/destructor.cpp
===
--- cfe/trunk/test/SemaCXX/destructor.cpp
+++ cfe/trunk/test/SemaCXX/destructor.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only 
-Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
+// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only 
-Wnon-virtual-dtor -Wdelete-non-virtual-dtor -fcxx-exceptions -verify %s
 // RUN: %clang_cc1 -std=c++11 -triple %ms_abi_triple -DMSABI -fsyntax-only 
-Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
 class A {
 public:
@@ -423,3 +423,11 @@
   (s.~S); // expected-error{{reference to destructor must be called}}
 }
 }
+
+class Invalid {
+~Invalid();
+UnknownType xx; // expected-error{{unknown type name}}
+};
+
+// The constructor definition should not have errors
+Invalid::~Invalid() {}
Index: cfe/trunk/lib/Sema/SemaDecl.cpp
===
--- cfe/trunk/lib/Sema/SemaDecl.cpp
+++ cfe/trunk/lib/Sema/SemaDecl.cpp
@@ -13862,15 +13862,17 @@
I = CXXRecord->conversion_begin(),
E = CXXRecord->conversion_end(); I != E; ++I)
   I.setAccess((*I)->getAccess());
-
-if (!CXXRecord->isDependentType()) {
-  if (CXXRecord->hasUserDeclaredDestructor()) {
-// Adjust user-defined destructor exception spec.
-if (getLangOpts().CPlusPlus11)
-  AdjustDestructorExceptionSpec(CXXRecord,
-CXXRecord->getDestructor());
-  }
+  }
+
+  if (!CXXRecord->isDependentType()) {
+if (CXXRecord->hasUserDeclaredDestructor()) {
+  // Adjust user-defined destructor exception spec.
+  if (getLangOpts().CPlusPlus11)
+AdjustDestructorExceptionSpec(CXXRecord,
+  CXXRecord->getDestructor());
+}
 
+if (!CXXRecord->isInvalidDecl()) {
   // Add any implicitly-declared members to this class.
   AddImplicitlyDeclaredMembersToClass(CXXRecord);
 


Index: cfe/trunk/test/SemaCXX/destructor.cpp
===
--- cfe/trunk/test/SemaCXX/destructor.cpp
+++ cfe/trunk/test/SemaCXX/destructor.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
+// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -fcxx-exceptions -verify %s
 // RUN: %clang_cc1 -std=c++11 -triple %ms_abi_triple -DMSABI -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
 class A {
 public:
@@ -423,3 +423,11 @@
   (s.~S); // expected-error{{reference to destructor must be called}}
 }
 }
+
+class Invalid {
+~Invalid();
+UnknownType xx; // expected-error{{unknown type name}}
+};
+
+// The constructor definition should not have errors
+Invalid::~Invalid() {}
Index: cfe/trunk/lib/Sema/SemaDecl.cpp
===
--- cfe/trunk/lib/Sema/SemaDecl.cpp
+++ cfe/trunk/lib/Sema/SemaDecl.cpp
@@ -13862,15 +13862,17 @@
I = CXXRecord->conversion_begin(),
E = CXXRecord->conversion_end(); I != E; ++I)
   I.setAccess((*I)->getAccess());
-
-if (!CXXRecord->isDependentType()) {
-  if (CXXRecord->hasUserDeclaredDestructor()) {
-// Adjust user-defined destructor exception spec.
-if (getLangOpts().CPlusPlus11)
-  AdjustDestructorExceptionSpec(CXXRecord,
-CXXRecord->getDestructor());
-  }
+  }
+
+  if (!CXXRecord->isDependentType()) {
+if (CXXRecord->hasUserDeclaredDestructor()) {
+  // Adjust user-defined destructor exception spec.
+  if (getLangOpts().CPlusPlus11)
+AdjustDestructorExceptionSpec(CXXRecord,
+  CXXRecord->getDestructor());
+}
 
+if (!CXXRecord->isInvalidDecl()) {
   // Add any implicitly-declared members to this class.
   AddImplicitlyDeclaredMembersToClass(CXXRecord);
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D19327: Keep invalid function body as part of the AST

2016-04-27 Thread Olivier Goffart via cfe-commits
ogoffart added inline comments.


Comment at: lib/Sema/SemaDecl.cpp:5044-5045
@@ -5043,4 +5043,4 @@
   // function template specialization, add it to the scope stack.
-  if (New->getDeclName() && AddToScope &&
-   !(D.isRedeclaration() && New->isInvalidDecl())) {
+  if (New->getDeclName() && AddToScope && !(D.isRedeclaration()
+  && New->isInvalidDecl() && !D.isFunctionDefinition())) {
 // Only make a locally-scoped extern declaration visible if it is the first

rsmith wrote:
> Can we delete the invalid-decl check entirely here? If it's doing something 
> important, we need to figure out what and make sure we preserve that intent 
> if it's important, but either way it doesn't make a lot of sense to me for 
> this to depend on whether the declaration has a definition.
I tried that, but then we have a failure in Sema/function-redecl.c and 
Sema/predefined-function.c


  int eli(float b); // expected-note {{previous declaration is here}} \
  int foo() {
int eli(int (int)); // expected-error {{conflicting types for 'eli'}}
eli(b); // expected-error{{passing 'int (int)' to parameter of incompatible 
type 'float'}}
 return 0;
   }

If we keep the invalid declaration, there would not be an error in the call to 
eli(b)

But is that a behaviour we would change?
  


http://reviews.llvm.org/D19327



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


Re: [PATCH] D19327: Keep invalid function body as part of the AST

2016-04-26 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

Ping?


http://reviews.llvm.org/D19327



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


[PATCH] D19763: Functions declared in a scope should not hide previous declaration in earlier scopes

2016-04-30 Thread Olivier Goffart via cfe-commits
ogoffart created this revision.
ogoffart added reviewers: cfe-commits, rsmith.

This code should be an error:

  void foo(int); 
  void f3() {
int foo(float);
{
  float foo(int); // expected-error {{functions that differ only in their 
return type cannot be overloaded}}
}
  }

the foo(float) function declared at function scope should not hide the 
float(int) while trying to redeclare functions.

http://reviews.llvm.org/D19763

Files:
  lib/Sema/SemaLookup.cpp
  test/SemaCXX/function-redecl.cpp

Index: test/SemaCXX/function-redecl.cpp
===
--- test/SemaCXX/function-redecl.cpp
+++ test/SemaCXX/function-redecl.cpp
@@ -7,7 +7,7 @@
 void bar(int); // expected-note 2{{previous declaration is here}}
   }
 
-  void foo(int); // expected-note 2{{previous declaration is here}}
+  void foo(int); // expected-note 3{{previous declaration is here}}
 
   void f2() {
 int foo(int); // expected-error {{functions that differ only in their 
return type cannot be overloaded}}
@@ -25,6 +25,13 @@
   }
 }
   }
+
+  void f3() {
+int foo(float);
+{
+  float foo(int); // expected-error {{functions that differ only in their 
return type cannot be overloaded}}
+}
+  }
 }
 
 class A {
Index: lib/Sema/SemaLookup.cpp
===
--- lib/Sema/SemaLookup.cpp
+++ lib/Sema/SemaLookup.cpp
@@ -1091,23 +1091,25 @@
 bool Found = false;
 for (; I != IEnd && S->isDeclScope(*I); ++I) {
   if (NamedDecl *ND = R.getAcceptableDecl(*I)) {
-if (NameKind == LookupRedeclarationWithLinkage) {
-  // Determine whether this (or a previous) declaration is
-  // out-of-scope.
-  if (!LeftStartingScope && !Initial->isDeclScope(*I))
-LeftStartingScope = true;
-
-  // If we found something outside of our starting scope that
-  // does not have linkage, skip it. If it's a template parameter,
+if (NameKind == LookupRedeclarationWithLinkage &&
+!(*I)->isTemplateParameter()) {
+  // If it's a template parameter,
   // we still find it, so we can diagnose the invalid redeclaration.
-  if (LeftStartingScope && !((*I)->hasLinkage()) &&
-  !(*I)->isTemplateParameter()) {
+
+  // Determine whether this (or a previous) declaration is
+  // out-of-scope.
+  if (!LeftStartingScope && !Initial->isDeclScope(*I))
+LeftStartingScope = true;
+
+  // If we found something outside of our starting scope that
+  // does not have linkage, skip it.
+  if (LeftStartingScope && !((*I)->hasLinkage())) {
 R.setShadowed();
 continue;
   }
+} else {
+  Found = true;
 }
-
-Found = true;
 R.addDecl(ND);
   }
 }


Index: test/SemaCXX/function-redecl.cpp
===
--- test/SemaCXX/function-redecl.cpp
+++ test/SemaCXX/function-redecl.cpp
@@ -7,7 +7,7 @@
 void bar(int); // expected-note 2{{previous declaration is here}}
   }
 
-  void foo(int); // expected-note 2{{previous declaration is here}}
+  void foo(int); // expected-note 3{{previous declaration is here}}
 
   void f2() {
 int foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}}
@@ -25,6 +25,13 @@
   }
 }
   }
+
+  void f3() {
+int foo(float);
+{
+  float foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}}
+}
+  }
 }
 
 class A {
Index: lib/Sema/SemaLookup.cpp
===
--- lib/Sema/SemaLookup.cpp
+++ lib/Sema/SemaLookup.cpp
@@ -1091,23 +1091,25 @@
 bool Found = false;
 for (; I != IEnd && S->isDeclScope(*I); ++I) {
   if (NamedDecl *ND = R.getAcceptableDecl(*I)) {
-if (NameKind == LookupRedeclarationWithLinkage) {
-  // Determine whether this (or a previous) declaration is
-  // out-of-scope.
-  if (!LeftStartingScope && !Initial->isDeclScope(*I))
-LeftStartingScope = true;
-
-  // If we found something outside of our starting scope that
-  // does not have linkage, skip it. If it's a template parameter,
+if (NameKind == LookupRedeclarationWithLinkage &&
+!(*I)->isTemplateParameter()) {
+  // If it's a template parameter,
   // we still find it, so we can diagnose the invalid redeclaration.
-  if (LeftStartingScope && !((*I)->hasLinkage()) &&
-  !(*I)->isTemplateParameter()) {
+
+  // Determine whether this (or a previous) declaration is
+  // out-of-scope.
+  if (!LeftStartingScope && !Initial->isDeclScope(*I))
+LeftStartingScope = true;
+
+  // If we found something outside of our starting scope that

Re: [PATCH] D19327: Keep invalid function body as part of the AST

2016-04-30 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

An alternative patch is uploaded there:  http://reviews.llvm.org/D19764


http://reviews.llvm.org/D19327



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


[PATCH] D19764: Keep invalid functions as part of the AST

2016-04-30 Thread Olivier Goffart via cfe-commits
ogoffart created this revision.
ogoffart added reviewers: cfe-commits, rsmith.

This is an alternative to http://reviews.llvm.org/D19327
We want to keep all the invalid function declarations as part of the AST.

This patch depends also on http://reviews.llvm.org/D19763 otherwise the tests 
in SemaCXX/function)redecl.cxx would fail as some invalid  declarations would 
be hiding previous ones, preventing errors

http://reviews.llvm.org/D19764

Files:
  lib/Sema/SemaDecl.cpp
  test/Misc/ast-dump-invalid.cpp
  test/Sema/predefined-function.c

Index: test/Sema/predefined-function.c
===
--- test/Sema/predefined-function.c
+++ test/Sema/predefined-function.c
@@ -4,14 +4,13 @@
 enum Test {A=-1};
 char *funk(enum Test x);
 
-int eli(float b); // expected-note {{previous declaration is here}} \
-// expected-note{{passing argument to parameter 'b' here}}
+int eli(float b); // expected-note {{previous declaration is here}}
 int b(int c) {return 1;}
 
 int foo();
 int foo() {
   int eli(int (int)); // expected-error {{conflicting types for 'eli'}}
-  eli(b); // expected-error{{passing 'int (int)' to parameter of incompatible 
type 'float'}}
+  eli(b);
   return 0;
 }
 
Index: test/Misc/ast-dump-invalid.cpp
===
--- test/Misc/ast-dump-invalid.cpp
+++ test/Misc/ast-dump-invalid.cpp
@@ -41,3 +41,24 @@
 // CHECK-NEXT: `-ImplicitCastExpr {{.*}}  'int' 

 // CHECK-NEXT:   `-DeclRefExpr {{.*}}  'int' lvalue ParmVar 
{{.*}} 'i' 'int'
 
+
+namespace TestInvalidFunctionDecl {
+struct Str {
+   double foo1(double, invalid_type);
+};
+double Str::foo1(double, invalid_type)
+{ return 45; }
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl
+// CHECK-NEXT: |-CXXRecordDecl {{.*}}  line:46:8 struct 
Str definition
+// CHECK-NEXT: | |-CXXRecordDecl {{.*}}  col:8 implicit struct 
Str
+// CHECK-NEXT: | `-CXXMethodDecl {{.*}}  col:11 invalid 
foo1 'double (double, int)'
+// CHECK-NEXT: |   |-ParmVarDecl {{.*}}  col:22 'double'
+// CHECK-NEXT: |   `-ParmVarDecl {{.*}}  col:36 
invalid 'int'
+// CHECK-NEXT: `-CXXMethodDecl {{.*}} parent {{.*}}  
line:49:13 invalid foo1 'double (double, int)'
+// CHECK-NEXT:   |-ParmVarDecl {{.*}}  col:24 'double'
+// CHECK-NEXT:   |-ParmVarDecl {{.*}}  col:38 invalid 
'int'
+// CHECK-NEXT:   `-CompoundStmt {{.*}} 
+// CHECK-NEXT: `-ReturnStmt {{.*}} 
+// CHECK-NEXT:   `-ImplicitCastExpr {{.*}}  'double' 

+// CHECK-NEXT: `-IntegerLiteral {{.*}}  'int' 45
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -5049,10 +5049,9 @@
   if (!New)
 return nullptr;
 
-  // If this has an identifier and is not an invalid redeclaration or 
-  // function template specialization, add it to the scope stack.
-  if (New->getDeclName() && AddToScope &&
-   !(D.isRedeclaration() && New->isInvalidDecl())) {
+  // If this has an identifier and is not a function template specialization,
+  // add it to the scope stack.
+  if (New->getDeclName() && AddToScope) {
 // Only make a locally-scoped extern declaration visible if it is the first
 // declaration of this entity. Qualified lookup for such an entity should
 // only find this declaration if there is no visible declaration of it.


Index: test/Sema/predefined-function.c
===
--- test/Sema/predefined-function.c
+++ test/Sema/predefined-function.c
@@ -4,14 +4,13 @@
 enum Test {A=-1};
 char *funk(enum Test x);
 
-int eli(float b); // expected-note {{previous declaration is here}} \
-// expected-note{{passing argument to parameter 'b' here}}
+int eli(float b); // expected-note {{previous declaration is here}}
 int b(int c) {return 1;}
 
 int foo();
 int foo() {
   int eli(int (int)); // expected-error {{conflicting types for 'eli'}}
-  eli(b); // expected-error{{passing 'int (int)' to parameter of incompatible type 'float'}}
+  eli(b);
   return 0;
 }
 
Index: test/Misc/ast-dump-invalid.cpp
===
--- test/Misc/ast-dump-invalid.cpp
+++ test/Misc/ast-dump-invalid.cpp
@@ -41,3 +41,24 @@
 // CHECK-NEXT: `-ImplicitCastExpr {{.*}}  'int' 
 // CHECK-NEXT:   `-DeclRefExpr {{.*}}  'int' lvalue ParmVar {{.*}} 'i' 'int'
 
+
+namespace TestInvalidFunctionDecl {
+struct Str {
+   double foo1(double, invalid_type);
+};
+double Str::foo1(double, invalid_type)
+{ return 45; }
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl
+// CHECK-NEXT: |-CXXRecordDecl {{.*}}  line:46:8 struct Str definition
+// CHECK-NEXT: | |-CXXRecordDecl {{.*}}  col:8 implicit struct Str
+// 

[PATCH] D20511: Fix crash while parsing variable template with variadic template arguments

2016-05-21 Thread Olivier Goffart via cfe-commits
ogoffart created this revision.
ogoffart added reviewers: cfe-commits, rsmith.

It is only a crash if the compiler optimize for this!=nullptr because
LocalInstantiationScope::getPartiallySubstitutedPack checks if 'this' is null.

(This is crashing when clang is compiled with GCC6)




http://reviews.llvm.org/D20511

Files:
  lib/Sema/SemaTemplateVariadic.cpp
  test/SemaCXX/cxx1y-variable-templates_top_level.cpp

Index: test/SemaCXX/cxx1y-variable-templates_top_level.cpp
===
--- test/SemaCXX/cxx1y-variable-templates_top_level.cpp
+++ test/SemaCXX/cxx1y-variable-templates_top_level.cpp
@@ -458,3 +458,9 @@
   template<> int g; // expected-error {{no variable template matches 
specialization; did you mean to use 'g' as function template instead?}}
 }
 
+#ifndef PRECXX11
+template  struct Variadic_t { };
+template  Variadic_t Variadic;
+auto variadic1 = Variadic<>;
+auto variadic2 = Variadic;
+#endif
Index: lib/Sema/SemaTemplateVariadic.cpp
===
--- lib/Sema/SemaTemplateVariadic.cpp
+++ lib/Sema/SemaTemplateVariadic.cpp
@@ -604,7 +604,7 @@
 //   Template argument deduction can extend the sequence of template 
 //   arguments corresponding to a template parameter pack, even when the
 //   sequence contains explicitly specified template arguments.
-if (!IsFunctionParameterPack) {
+if (!IsFunctionParameterPack && CurrentInstantiationScope) {
   if (NamedDecl *PartialPack 
 = 
CurrentInstantiationScope->getPartiallySubstitutedPack()){
 unsigned PartialDepth, PartialIndex;


Index: test/SemaCXX/cxx1y-variable-templates_top_level.cpp
===
--- test/SemaCXX/cxx1y-variable-templates_top_level.cpp
+++ test/SemaCXX/cxx1y-variable-templates_top_level.cpp
@@ -458,3 +458,9 @@
   template<> int g; // expected-error {{no variable template matches specialization; did you mean to use 'g' as function template instead?}}
 }
 
+#ifndef PRECXX11
+template  struct Variadic_t { };
+template  Variadic_t Variadic;
+auto variadic1 = Variadic<>;
+auto variadic2 = Variadic;
+#endif
Index: lib/Sema/SemaTemplateVariadic.cpp
===
--- lib/Sema/SemaTemplateVariadic.cpp
+++ lib/Sema/SemaTemplateVariadic.cpp
@@ -604,7 +604,7 @@
 //   Template argument deduction can extend the sequence of template 
 //   arguments corresponding to a template parameter pack, even when the
 //   sequence contains explicitly specified template arguments.
-if (!IsFunctionParameterPack) {
+if (!IsFunctionParameterPack && CurrentInstantiationScope) {
   if (NamedDecl *PartialPack 
 = CurrentInstantiationScope->getPartiallySubstitutedPack()){
 unsigned PartialDepth, PartialIndex;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18080: CIndex: add support for static_assert

2016-04-20 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

Ping?


http://reviews.llvm.org/D18080



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


Re: [PATCH] D18081: Make sizeof and alignof a CXCursor_UnaryExpr

2016-04-20 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

Ping?


http://reviews.llvm.org/D18081



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


[PATCH] D19327: Keep invalid function body as part of the AST

2016-04-20 Thread Olivier Goffart via cfe-commits
ogoffart created this revision.
ogoffart added reviewers: cfe-commits, rsmith.


struct XX {
   double foo(invalid_type xx);
};
double XX::foo(invalid_type xx)
{ 
   return 45; 
}

We should keep XX::foo and its function body as part of the AST so tools can 
still do something with the body even if the definition is wrong.
Inline function would already be kept, but not when they are redeclarations.

http://reviews.llvm.org/D19327

Files:
  lib/Sema/SemaDecl.cpp
  test/Misc/ast-dump-invalid.cpp

Index: test/Misc/ast-dump-invalid.cpp
===
--- test/Misc/ast-dump-invalid.cpp
+++ test/Misc/ast-dump-invalid.cpp
@@ -41,3 +41,24 @@
 // CHECK-NEXT: `-ImplicitCastExpr {{.*}}  'int' 

 // CHECK-NEXT:   `-DeclRefExpr {{.*}}  'int' lvalue ParmVar 
{{.*}} 'i' 'int'
 
+
+namespace TestInvalidFunctionDecl {
+struct Str {
+   double foo1(double, invalid_type);
+};
+double Str::foo1(double, invalid_type)
+{ return 45; }
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl
+// CHECK-NEXT: |-CXXRecordDecl {{.*}}  line:46:8 struct 
Str definition
+// CHECK-NEXT: | |-CXXRecordDecl {{.*}}  col:8 implicit struct 
Str
+// CHECK-NEXT: | `-CXXMethodDecl {{.*}}  col:11 invalid 
foo1 'double (double, int)'
+// CHECK-NEXT: |   |-ParmVarDecl {{.*}}  col:22 'double'
+// CHECK-NEXT: |   `-ParmVarDecl {{.*}}  col:36 
invalid 'int'
+// CHECK-NEXT: `-CXXMethodDecl {{.*}} parent {{.*}}  
line:49:13 invalid foo1 'double (double, int)'
+// CHECK-NEXT:   |-ParmVarDecl {{.*}}  col:24 'double'
+// CHECK-NEXT:   |-ParmVarDecl {{.*}}  col:38 invalid 
'int'
+// CHECK-NEXT:   `-CompoundStmt {{.*}} 
+// CHECK-NEXT: `-ReturnStmt {{.*}} 
+// CHECK-NEXT:   `-ImplicitCastExpr {{.*}}  'double' 

+// CHECK-NEXT: `-IntegerLiteral {{.*}}  'int' 45
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -5041,8 +5041,8 @@
 
   // If this has an identifier and is not an invalid redeclaration or 
   // function template specialization, add it to the scope stack.
-  if (New->getDeclName() && AddToScope &&
-   !(D.isRedeclaration() && New->isInvalidDecl())) {
+  if (New->getDeclName() && AddToScope && !(D.isRedeclaration()
+  && New->isInvalidDecl() && !D.isFunctionDefinition())) {
 // Only make a locally-scoped extern declaration visible if it is the first
 // declaration of this entity. Qualified lookup for such an entity should
 // only find this declaration if there is no visible declaration of it.


Index: test/Misc/ast-dump-invalid.cpp
===
--- test/Misc/ast-dump-invalid.cpp
+++ test/Misc/ast-dump-invalid.cpp
@@ -41,3 +41,24 @@
 // CHECK-NEXT: `-ImplicitCastExpr {{.*}}  'int' 
 // CHECK-NEXT:   `-DeclRefExpr {{.*}}  'int' lvalue ParmVar {{.*}} 'i' 'int'
 
+
+namespace TestInvalidFunctionDecl {
+struct Str {
+   double foo1(double, invalid_type);
+};
+double Str::foo1(double, invalid_type)
+{ return 45; }
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl
+// CHECK-NEXT: |-CXXRecordDecl {{.*}}  line:46:8 struct Str definition
+// CHECK-NEXT: | |-CXXRecordDecl {{.*}}  col:8 implicit struct Str
+// CHECK-NEXT: | `-CXXMethodDecl {{.*}}  col:11 invalid foo1 'double (double, int)'
+// CHECK-NEXT: |   |-ParmVarDecl {{.*}}  col:22 'double'
+// CHECK-NEXT: |   `-ParmVarDecl {{.*}}  col:36 invalid 'int'
+// CHECK-NEXT: `-CXXMethodDecl {{.*}} parent {{.*}}  line:49:13 invalid foo1 'double (double, int)'
+// CHECK-NEXT:   |-ParmVarDecl {{.*}}  col:24 'double'
+// CHECK-NEXT:   |-ParmVarDecl {{.*}}  col:38 invalid 'int'
+// CHECK-NEXT:   `-CompoundStmt {{.*}} 
+// CHECK-NEXT: `-ReturnStmt {{.*}} 
+// CHECK-NEXT:   `-ImplicitCastExpr {{.*}}  'double' 
+// CHECK-NEXT: `-IntegerLiteral {{.*}}  'int' 45
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -5041,8 +5041,8 @@
 
   // If this has an identifier and is not an invalid redeclaration or 
   // function template specialization, add it to the scope stack.
-  if (New->getDeclName() && AddToScope &&
-   !(D.isRedeclaration() && New->isInvalidDecl())) {
+  if (New->getDeclName() && AddToScope && !(D.isRedeclaration()
+  && New->isInvalidDecl() && !D.isFunctionDefinition())) {
 // Only make a locally-scoped extern declaration visible if it is the first
 // declaration of this entity. Qualified lookup for such an entity should
 // only find this declaration if there is no visible declaration of it.

Re: [PATCH] D19764: Keep invalid functions as part of the AST

2016-05-08 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

Ping?


http://reviews.llvm.org/D19764



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


[PATCH] D20054: Fix spurious warnings about unused private field

2016-05-08 Thread Olivier Goffart via cfe-commits
ogoffart created this revision.
ogoffart added reviewers: cfe-commits, djasper.

If the address of a field is taken as a pointer to member, we should
not warn that the field is not used.

Normaly, yse of fields are done from MemberExpr, but in case of pointer to
 member, it is in a DeclRefExpr


http://reviews.llvm.org/D20054

Files:
  lib/Sema/SemaExpr.cpp
  test/SemaCXX/warn-unused-private-field.cpp

Index: test/SemaCXX/warn-unused-private-field.cpp
===
--- test/SemaCXX/warn-unused-private-field.cpp
+++ test/SemaCXX/warn-unused-private-field.cpp
@@ -128,6 +128,7 @@
 int *use = _reference_;
 int test[2];
 test[as_array_index_] = 42;
+int EverythingUsed::*ptr = ::by_pointer_to_member_;
   }
 
   template
@@ -142,6 +143,7 @@
   int by_template_function_;
   int as_array_index_;
   int by_initializer_;
+  int by_pointer_to_member_;
 };
 
 class HasFeatureTest {
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -1736,10 +1736,12 @@
   !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart()))
   recordUseOfEvaluatedWeak(E);
 
-  // Just in case we're building an illegal pointer-to-member.
-  FieldDecl *FD = dyn_cast(D);
-  if (FD && FD->isBitField())
-E->setObjectKind(OK_BitField);
+  if (FieldDecl *FD = dyn_cast(D)) {
+UnusedPrivateFields.remove(FD);
+// Just in case we're building an illegal pointer-to-member.
+if (FD->isBitField())
+  E->setObjectKind(OK_BitField);
+  }
 
   return E;
 }


Index: test/SemaCXX/warn-unused-private-field.cpp
===
--- test/SemaCXX/warn-unused-private-field.cpp
+++ test/SemaCXX/warn-unused-private-field.cpp
@@ -128,6 +128,7 @@
 int *use = _reference_;
 int test[2];
 test[as_array_index_] = 42;
+int EverythingUsed::*ptr = ::by_pointer_to_member_;
   }
 
   template
@@ -142,6 +143,7 @@
   int by_template_function_;
   int as_array_index_;
   int by_initializer_;
+  int by_pointer_to_member_;
 };
 
 class HasFeatureTest {
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -1736,10 +1736,12 @@
   !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart()))
   recordUseOfEvaluatedWeak(E);
 
-  // Just in case we're building an illegal pointer-to-member.
-  FieldDecl *FD = dyn_cast(D);
-  if (FD && FD->isBitField())
-E->setObjectKind(OK_BitField);
+  if (FieldDecl *FD = dyn_cast(D)) {
+UnusedPrivateFields.remove(FD);
+// Just in case we're building an illegal pointer-to-member.
+if (FD->isBitField())
+  E->setObjectKind(OK_BitField);
+  }
 
   return E;
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r268895 - Fix spurious warnings about unused private field

2016-05-09 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Mon May  9 02:09:51 2016
New Revision: 268895

URL: http://llvm.org/viewvc/llvm-project?rev=268895=rev
Log:
Fix spurious warnings about unused private field

If the address of a field is taken as a pointer to member, we should
not warn that the field is not used.

Normaly, yse of fields are done from MemberExpr, but in case of pointer to
member, it is in a DeclRefExpr

Differential Revision: http://reviews.llvm.org/D20054

Modified:
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=268895=268894=268895=diff
==
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon May  9 02:09:51 2016
@@ -1736,10 +1736,12 @@ Sema::BuildDeclRefExpr(ValueDecl *D, Qua
   !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart()))
   recordUseOfEvaluatedWeak(E);
 
-  // Just in case we're building an illegal pointer-to-member.
-  FieldDecl *FD = dyn_cast(D);
-  if (FD && FD->isBitField())
-E->setObjectKind(OK_BitField);
+  if (FieldDecl *FD = dyn_cast(D)) {
+UnusedPrivateFields.remove(FD);
+// Just in case we're building an illegal pointer-to-member.
+if (FD->isBitField())
+  E->setObjectKind(OK_BitField);
+  }
 
   return E;
 }

Modified: cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp?rev=268895=268894=268895=diff
==
--- cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp Mon May  9 02:09:51 
2016
@@ -128,6 +128,7 @@ class EverythingUsed {
 int *use = _reference_;
 int test[2];
 test[as_array_index_] = 42;
+int EverythingUsed::*ptr = ::by_pointer_to_member_;
   }
 
   template
@@ -142,6 +143,7 @@ class EverythingUsed {
   int by_template_function_;
   int as_array_index_;
   int by_initializer_;
+  int by_pointer_to_member_;
 };
 
 class HasFeatureTest {


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


Re: [PATCH] D20054: Fix spurious warnings about unused private field

2016-05-09 Thread Olivier Goffart via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL268895: Fix spurious warnings about unused private field 
(authored by ogoffart).

Changed prior to commit:
  http://reviews.llvm.org/D20054?vs=56514=56530#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D20054

Files:
  cfe/trunk/lib/Sema/SemaExpr.cpp
  cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp

Index: cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp
===
--- cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp
+++ cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp
@@ -128,6 +128,7 @@
 int *use = _reference_;
 int test[2];
 test[as_array_index_] = 42;
+int EverythingUsed::*ptr = ::by_pointer_to_member_;
   }
 
   template
@@ -142,6 +143,7 @@
   int by_template_function_;
   int as_array_index_;
   int by_initializer_;
+  int by_pointer_to_member_;
 };
 
 class HasFeatureTest {
Index: cfe/trunk/lib/Sema/SemaExpr.cpp
===
--- cfe/trunk/lib/Sema/SemaExpr.cpp
+++ cfe/trunk/lib/Sema/SemaExpr.cpp
@@ -1736,10 +1736,12 @@
   !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart()))
   recordUseOfEvaluatedWeak(E);
 
-  // Just in case we're building an illegal pointer-to-member.
-  FieldDecl *FD = dyn_cast(D);
-  if (FD && FD->isBitField())
-E->setObjectKind(OK_BitField);
+  if (FieldDecl *FD = dyn_cast(D)) {
+UnusedPrivateFields.remove(FD);
+// Just in case we're building an illegal pointer-to-member.
+if (FD->isBitField())
+  E->setObjectKind(OK_BitField);
+  }
 
   return E;
 }


Index: cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp
===
--- cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp
+++ cfe/trunk/test/SemaCXX/warn-unused-private-field.cpp
@@ -128,6 +128,7 @@
 int *use = _reference_;
 int test[2];
 test[as_array_index_] = 42;
+int EverythingUsed::*ptr = ::by_pointer_to_member_;
   }
 
   template
@@ -142,6 +143,7 @@
   int by_template_function_;
   int as_array_index_;
   int by_initializer_;
+  int by_pointer_to_member_;
 };
 
 class HasFeatureTest {
Index: cfe/trunk/lib/Sema/SemaExpr.cpp
===
--- cfe/trunk/lib/Sema/SemaExpr.cpp
+++ cfe/trunk/lib/Sema/SemaExpr.cpp
@@ -1736,10 +1736,12 @@
   !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart()))
   recordUseOfEvaluatedWeak(E);
 
-  // Just in case we're building an illegal pointer-to-member.
-  FieldDecl *FD = dyn_cast(D);
-  if (FD && FD->isBitField())
-E->setObjectKind(OK_BitField);
+  if (FieldDecl *FD = dyn_cast(D)) {
+UnusedPrivateFields.remove(FD);
+// Just in case we're building an illegal pointer-to-member.
+if (FD->isBitField())
+  E->setObjectKind(OK_BitField);
+  }
 
   return E;
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D23837: Fix colored diagnostics from tools

2016-08-25 Thread Olivier Goffart via cfe-commits
ogoffart updated this revision to Diff 69221.
ogoffart added a comment.

Added a test.


https://reviews.llvm.org/D23837

Files:
  lib/Tooling/Tooling.cpp
  unittests/Tooling/ToolingTest.cpp

Index: unittests/Tooling/ToolingTest.cpp
===
--- unittests/Tooling/ToolingTest.cpp
+++ unittests/Tooling/ToolingTest.cpp
@@ -332,6 +332,47 @@
   EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str()));
 }
 
+struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction {
+  CheckColoredDiagnosticsAction(bool ShouldShowColor)
+  : ShouldShowColor(ShouldShowColor) {}
+  std::unique_ptr CreateASTConsumer(CompilerInstance ,
+ StringRef) override {
+if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor)
+  Compiler.getDiagnostics().Report(
+  Compiler.getDiagnostics().getCustomDiagID(
+  DiagnosticsEngine::Fatal,
+  "getDiagnosticOpts().ShowColors != ShouldShowColor"));
+return llvm::make_unique();
+  }
+
+private:
+  bool ShouldShowColor = true;
+};
+
+TEST(runToolOnCodeWithArgs, DiagnosticsColor) {
+  // Defaults to showing the colors.
+  EXPECT_TRUE(
+  runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "", {}));
+  // Check that this test would fail if ShowColors is not what it should.
+  EXPECT_FALSE(
+  runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "", {}));
+
+  // Last argument wins.
+  EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), 
"",
+{"-fcolor-diagnostics"}));
+  EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false),
+"", {"-fno-color-diagnostics"}));
+  EXPECT_TRUE(
+  runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "",
+{"-fno-color-diagnostics", 
"-fcolor-diagnostics"}));
+  EXPECT_TRUE(
+  runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "",
+{"-fcolor-diagnostics", 
"-fno-color-diagnostics"}));
+  EXPECT_TRUE(runToolOnCodeWithArgs(
+  new CheckColoredDiagnosticsAction(true), "",
+  {"-fno-color-diagnostics", "-fdiagnostics-color=always"}));
+}
+
 TEST(ClangToolTest, ArgumentAdjusters) {
   FixedCompilationDatabase Compilations("/", std::vector());
 
Index: lib/Tooling/Tooling.cpp
===
--- lib/Tooling/Tooling.cpp
+++ lib/Tooling/Tooling.cpp
@@ -15,6 +15,7 @@
 #include "clang/Tooling/Tooling.h"
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
 #include "clang/Driver/Tool.h"
 #include "clang/Driver/ToolChain.h"
 #include "clang/Frontend/ASTUnit.h"
@@ -26,6 +27,7 @@
 #include "clang/Tooling/CompilationDatabase.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/FileSystem.h"
@@ -241,6 +243,12 @@
 Argv.push_back(Str.c_str());
   const char *const BinaryName = Argv[0];
   IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions();
+  unsigned MissingArgIndex, MissingArgCount;
+  llvm::opt::InputArgList ParsedArgs =
+  driver::createDriverOptTable()->ParseArgs(
+  ArrayRef(Argv).slice(1), MissingArgIndex,
+  MissingArgCount);
+  ParseDiagnosticArgs(*DiagOpts, ParsedArgs);
   TextDiagnosticPrinter DiagnosticPrinter(
   llvm::errs(), &*DiagOpts);
   DiagnosticsEngine Diagnostics(


Index: unittests/Tooling/ToolingTest.cpp
===
--- unittests/Tooling/ToolingTest.cpp
+++ unittests/Tooling/ToolingTest.cpp
@@ -332,6 +332,47 @@
   EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str()));
 }
 
+struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction {
+  CheckColoredDiagnosticsAction(bool ShouldShowColor)
+  : ShouldShowColor(ShouldShowColor) {}
+  std::unique_ptr CreateASTConsumer(CompilerInstance ,
+ StringRef) override {
+if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor)
+  Compiler.getDiagnostics().Report(
+  Compiler.getDiagnostics().getCustomDiagID(
+  DiagnosticsEngine::Fatal,
+  "getDiagnosticOpts().ShowColors != ShouldShowColor"));
+return llvm::make_unique();
+  }
+
+private:
+  bool ShouldShowColor = true;
+};
+
+TEST(runToolOnCodeWithArgs, DiagnosticsColor) {
+  // Defaults to showing the colors.
+  EXPECT_TRUE(
+  runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "", {}));
+  // Check that this test would fail if ShowColors is not what it should.
+  EXPECT_FALSE(
+  runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "", {}));
+
+  // Last argument wins.
+  

Re: [PATCH] D23837: Fix colored diagnostics from tools

2016-08-25 Thread Olivier Goffart via cfe-commits
ogoffart updated this revision to Diff 69225.
ogoffart added a comment.

This new patch make sure the test run fine as part of the testsuite, where the 
output is not a terminal and the color are disabled by default


https://reviews.llvm.org/D23837

Files:
  lib/Tooling/Tooling.cpp
  unittests/Tooling/ToolingTest.cpp

Index: unittests/Tooling/ToolingTest.cpp
===
--- unittests/Tooling/ToolingTest.cpp
+++ unittests/Tooling/ToolingTest.cpp
@@ -332,6 +332,44 @@
   EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str()));
 }
 
+struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction {
+  CheckColoredDiagnosticsAction(bool ShouldShowColor)
+  : ShouldShowColor(ShouldShowColor) {}
+  std::unique_ptr CreateASTConsumer(CompilerInstance ,
+ StringRef) override {
+if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor)
+  Compiler.getDiagnostics().Report(
+  Compiler.getDiagnostics().getCustomDiagID(
+  DiagnosticsEngine::Fatal,
+  "getDiagnosticOpts().ShowColors != ShouldShowColor"));
+return llvm::make_unique();
+  }
+
+private:
+  bool ShouldShowColor = true;
+};
+
+TEST(runToolOnCodeWithArgs, DiagnosticsColor) {
+
+  EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), 
"",
+{"-fcolor-diagnostics"}));
+  EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false),
+"", {"-fno-color-diagnostics"}));
+  EXPECT_TRUE(
+  runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "",
+{"-fno-color-diagnostics", 
"-fcolor-diagnostics"}));
+  EXPECT_TRUE(
+  runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "",
+{"-fcolor-diagnostics", 
"-fno-color-diagnostics"}));
+  EXPECT_TRUE(runToolOnCodeWithArgs(
+  new CheckColoredDiagnosticsAction(true), "",
+  {"-fno-color-diagnostics", "-fdiagnostics-color=always"}));
+
+  // Check that this test would fail if ShowColors is not what it should.
+  EXPECT_FALSE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false),
+ "", {"-fcolor-diagnostics"}));
+}
+
 TEST(ClangToolTest, ArgumentAdjusters) {
   FixedCompilationDatabase Compilations("/", std::vector());
 
Index: lib/Tooling/Tooling.cpp
===
--- lib/Tooling/Tooling.cpp
+++ lib/Tooling/Tooling.cpp
@@ -15,6 +15,7 @@
 #include "clang/Tooling/Tooling.h"
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
 #include "clang/Driver/Tool.h"
 #include "clang/Driver/ToolChain.h"
 #include "clang/Frontend/ASTUnit.h"
@@ -26,6 +27,7 @@
 #include "clang/Tooling/CompilationDatabase.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/FileSystem.h"
@@ -241,6 +243,12 @@
 Argv.push_back(Str.c_str());
   const char *const BinaryName = Argv[0];
   IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions();
+  unsigned MissingArgIndex, MissingArgCount;
+  llvm::opt::InputArgList ParsedArgs =
+  driver::createDriverOptTable()->ParseArgs(
+  ArrayRef(Argv).slice(1), MissingArgIndex,
+  MissingArgCount);
+  ParseDiagnosticArgs(*DiagOpts, ParsedArgs);
   TextDiagnosticPrinter DiagnosticPrinter(
   llvm::errs(), &*DiagOpts);
   DiagnosticsEngine Diagnostics(


Index: unittests/Tooling/ToolingTest.cpp
===
--- unittests/Tooling/ToolingTest.cpp
+++ unittests/Tooling/ToolingTest.cpp
@@ -332,6 +332,44 @@
   EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str()));
 }
 
+struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction {
+  CheckColoredDiagnosticsAction(bool ShouldShowColor)
+  : ShouldShowColor(ShouldShowColor) {}
+  std::unique_ptr CreateASTConsumer(CompilerInstance ,
+ StringRef) override {
+if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor)
+  Compiler.getDiagnostics().Report(
+  Compiler.getDiagnostics().getCustomDiagID(
+  DiagnosticsEngine::Fatal,
+  "getDiagnosticOpts().ShowColors != ShouldShowColor"));
+return llvm::make_unique();
+  }
+
+private:
+  bool ShouldShowColor = true;
+};
+
+TEST(runToolOnCodeWithArgs, DiagnosticsColor) {
+
+  EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "",
+{"-fcolor-diagnostics"}));
+  EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false),
+"", {"-fno-color-diagnostics"}));
+  EXPECT_TRUE(
+  

Re: [PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11

2016-08-25 Thread Olivier Goffart via cfe-commits
ogoffart updated this revision to Diff 69223.
ogoffart added a comment.

Made the requested changes


https://reviews.llvm.org/D21502

Files:
  lib/Parse/ParseCXXInlineMethods.cpp
  test/CodeCompletion/ctor-initializer.cpp

Index: test/CodeCompletion/ctor-initializer.cpp
===
--- test/CodeCompletion/ctor-initializer.cpp
+++ test/CodeCompletion/ctor-initializer.cpp
@@ -1,11 +1,13 @@
 struct Base1 {
   Base1() : {}
-  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
   // CHECK-CC1: COMPLETION: Pattern : member1(<#args#>)
   // CHECK-CC1: COMPLETION: Pattern : member2(<#args#>
 
   Base1(int) : member1(123), {}
-  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:7:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:8:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:8:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
   // CHECK-CC2-NOT: COMPLETION: Pattern : member1(<#args#>)
   // CHECK-CC2: COMPLETION: Pattern : member2(<#args#>
 
@@ -21,21 +23,40 @@
 };
 
 Derived::Derived() : {}
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:25:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:25:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
 // CHECK-CC3: COMPLETION: Pattern : Base1(<#args#>)
 // CHECK-CC3: COMPLETION: Pattern : deriv1(<#args#>)
 
 Derived::Derived(int) try : {
 } catch (...) {
 }
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:28:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:31:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:31:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
 // CHECK-CC4: COMPLETION: Pattern : Base1(<#args#>)
 // CHECK-CC4: COMPLETION: Pattern : deriv1(<#args#>)
 
 Derived::Derived(float) try : Base1(),
 {
 } catch (...) {
 }
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:35:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:39:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:39:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
 // CHECK-CC5-NOT: COMPLETION: Pattern : Base1(<#args#>)
 // CHECK-CC5: COMPLETION: Pattern : deriv1(<#args#>)
+
+struct A {
+  A() : , member2() {}
+  // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:49:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:49:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s
+  // CHECK-CC6: COMPLETION: Pattern : member1(<#args#>
+  int member1, member2;
+};
+
+struct B {
+  B() : member2() {}
+  // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:57:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:57:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
+  // CHECK-CC7: COMPLETION: Pattern : member1(<#args#>
+  int member1, member2;
+};
Index: lib/Parse/ParseCXXInlineMethods.cpp
===
--- lib/Parse/ParseCXXInlineMethods.cpp
+++ lib/Parse/ParseCXXInlineMethods.cpp
@@ -832,22 +832,30 @@
 }
   }
 
-  if (Tok.isOneOf(tok::identifier, tok::kw_template)) {
+  if (Tok.is(tok::identifier)) {
 Toks.push_back(Tok);
 ConsumeToken();
-  } else if (Tok.is(tok::code_completion)) {
-Toks.push_back(Tok);
-ConsumeCodeCompletionToken();
-// Consume the rest of the initializers permissively.
-// FIXME: We should be able to perform code-completion here even if
-//there isn't a subsequent '{' token.
-MightBeTemplateArgument = true;
-break;
   } else {
 break;
   }
 } while (Tok.is(tok::coloncolon));
 
+if (Tok.is(tok::code_completion)) {
+  Toks.push_back(Tok);
+  ConsumeCodeCompletionToken();
+  if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype)) {
+// Could be the start of another member initializer (the ',' has not
+// been written yet)
+continue;
+  }
+}
+
+if (Tok.is(tok::comma)) {
+  // The initialization is missing, we'll diagnose 

Re: [PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11

2016-08-25 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

Regarding this:

  struct Foo {
Foo() : some_long_x(0), some_| {}
int some_long_x, some_long_y;
  };

That should work fine because the token before the { is the code completion 
token, not an identifier.  This is basicaly tested by the test with CHECK-CC2.

However, this does not work because if the completion is within an identifier, 
the Lexer will abort by calling cutOffLexing from Lexer::LexIdentifier


https://reviews.llvm.org/D21502



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


Re: [PATCH] D23837: Fix colored diagnostics from tools

2016-08-30 Thread Olivier Goffart via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL280118: Fix colored diagnostics from tools (authored by 
ogoffart).

Changed prior to commit:
  https://reviews.llvm.org/D23837?vs=69225=69725#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D23837

Files:
  cfe/trunk/lib/Tooling/Tooling.cpp
  cfe/trunk/unittests/Tooling/ToolingTest.cpp

Index: cfe/trunk/lib/Tooling/Tooling.cpp
===
--- cfe/trunk/lib/Tooling/Tooling.cpp
+++ cfe/trunk/lib/Tooling/Tooling.cpp
@@ -15,6 +15,7 @@
 #include "clang/Tooling/Tooling.h"
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
 #include "clang/Driver/Tool.h"
 #include "clang/Driver/ToolChain.h"
 #include "clang/Frontend/ASTUnit.h"
@@ -26,6 +27,7 @@
 #include "clang/Tooling/CompilationDatabase.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/FileSystem.h"
@@ -241,6 +243,12 @@
 Argv.push_back(Str.c_str());
   const char *const BinaryName = Argv[0];
   IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions();
+  unsigned MissingArgIndex, MissingArgCount;
+  llvm::opt::InputArgList ParsedArgs =
+  driver::createDriverOptTable()->ParseArgs(
+  ArrayRef(Argv).slice(1), MissingArgIndex,
+  MissingArgCount);
+  ParseDiagnosticArgs(*DiagOpts, ParsedArgs);
   TextDiagnosticPrinter DiagnosticPrinter(
   llvm::errs(), &*DiagOpts);
   DiagnosticsEngine Diagnostics(
Index: cfe/trunk/unittests/Tooling/ToolingTest.cpp
===
--- cfe/trunk/unittests/Tooling/ToolingTest.cpp
+++ cfe/trunk/unittests/Tooling/ToolingTest.cpp
@@ -332,6 +332,44 @@
   EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str()));
 }
 
+struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction {
+  CheckColoredDiagnosticsAction(bool ShouldShowColor)
+  : ShouldShowColor(ShouldShowColor) {}
+  std::unique_ptr CreateASTConsumer(CompilerInstance ,
+ StringRef) override {
+if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor)
+  Compiler.getDiagnostics().Report(
+  Compiler.getDiagnostics().getCustomDiagID(
+  DiagnosticsEngine::Fatal,
+  "getDiagnosticOpts().ShowColors != ShouldShowColor"));
+return llvm::make_unique();
+  }
+
+private:
+  bool ShouldShowColor = true;
+};
+
+TEST(runToolOnCodeWithArgs, DiagnosticsColor) {
+
+  EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), 
"",
+{"-fcolor-diagnostics"}));
+  EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false),
+"", {"-fno-color-diagnostics"}));
+  EXPECT_TRUE(
+  runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "",
+{"-fno-color-diagnostics", 
"-fcolor-diagnostics"}));
+  EXPECT_TRUE(
+  runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "",
+{"-fcolor-diagnostics", 
"-fno-color-diagnostics"}));
+  EXPECT_TRUE(runToolOnCodeWithArgs(
+  new CheckColoredDiagnosticsAction(true), "",
+  {"-fno-color-diagnostics", "-fdiagnostics-color=always"}));
+
+  // Check that this test would fail if ShowColors is not what it should.
+  EXPECT_FALSE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false),
+ "", {"-fcolor-diagnostics"}));
+}
+
 TEST(ClangToolTest, ArgumentAdjusters) {
   FixedCompilationDatabase Compilations("/", std::vector());
 


Index: cfe/trunk/lib/Tooling/Tooling.cpp
===
--- cfe/trunk/lib/Tooling/Tooling.cpp
+++ cfe/trunk/lib/Tooling/Tooling.cpp
@@ -15,6 +15,7 @@
 #include "clang/Tooling/Tooling.h"
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
 #include "clang/Driver/Tool.h"
 #include "clang/Driver/ToolChain.h"
 #include "clang/Frontend/ASTUnit.h"
@@ -26,6 +27,7 @@
 #include "clang/Tooling/CompilationDatabase.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/FileSystem.h"
@@ -241,6 +243,12 @@
 Argv.push_back(Str.c_str());
   const char *const BinaryName = Argv[0];
   IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions();
+  unsigned MissingArgIndex, MissingArgCount;
+  llvm::opt::InputArgList ParsedArgs =
+  driver::createDriverOptTable()->ParseArgs(
+  ArrayRef(Argv).slice(1), MissingArgIndex,
+  MissingArgCount);
+  ParseDiagnosticArgs(*DiagOpts, ParsedArgs);
   TextDiagnosticPrinter DiagnosticPrinter(
  

r280118 - Fix colored diagnostics from tools

2016-08-30 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Tue Aug 30 12:42:29 2016
New Revision: 280118

URL: http://llvm.org/viewvc/llvm-project?rev=280118=rev
Log:
Fix colored diagnostics from tools

r271042 changed the way the diagnostic arguments are parsed. It assumes that
the diagnostics options were already parsed by the "Driver".
For tools using clang::Tooling, the diagnostics argument were not parsed.

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

Modified:
cfe/trunk/lib/Tooling/Tooling.cpp
cfe/trunk/unittests/Tooling/ToolingTest.cpp

Modified: cfe/trunk/lib/Tooling/Tooling.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Tooling.cpp?rev=280118=280117=280118=diff
==
--- cfe/trunk/lib/Tooling/Tooling.cpp (original)
+++ cfe/trunk/lib/Tooling/Tooling.cpp Tue Aug 30 12:42:29 2016
@@ -15,6 +15,7 @@
 #include "clang/Tooling/Tooling.h"
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
 #include "clang/Driver/Tool.h"
 #include "clang/Driver/ToolChain.h"
 #include "clang/Frontend/ASTUnit.h"
@@ -26,6 +27,7 @@
 #include "clang/Tooling/CompilationDatabase.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/FileSystem.h"
@@ -241,6 +243,12 @@ bool ToolInvocation::run() {
 Argv.push_back(Str.c_str());
   const char *const BinaryName = Argv[0];
   IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions();
+  unsigned MissingArgIndex, MissingArgCount;
+  llvm::opt::InputArgList ParsedArgs =
+  driver::createDriverOptTable()->ParseArgs(
+  ArrayRef(Argv).slice(1), MissingArgIndex,
+  MissingArgCount);
+  ParseDiagnosticArgs(*DiagOpts, ParsedArgs);
   TextDiagnosticPrinter DiagnosticPrinter(
   llvm::errs(), &*DiagOpts);
   DiagnosticsEngine Diagnostics(

Modified: cfe/trunk/unittests/Tooling/ToolingTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/ToolingTest.cpp?rev=280118=280117=280118=diff
==
--- cfe/trunk/unittests/Tooling/ToolingTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/ToolingTest.cpp Tue Aug 30 12:42:29 2016
@@ -332,6 +332,44 @@ TEST(runToolOnCodeWithArgs, TestNoDepFil
   EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str()));
 }
 
+struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction {
+  CheckColoredDiagnosticsAction(bool ShouldShowColor)
+  : ShouldShowColor(ShouldShowColor) {}
+  std::unique_ptr CreateASTConsumer(CompilerInstance ,
+ StringRef) override {
+if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor)
+  Compiler.getDiagnostics().Report(
+  Compiler.getDiagnostics().getCustomDiagID(
+  DiagnosticsEngine::Fatal,
+  "getDiagnosticOpts().ShowColors != ShouldShowColor"));
+return llvm::make_unique();
+  }
+
+private:
+  bool ShouldShowColor = true;
+};
+
+TEST(runToolOnCodeWithArgs, DiagnosticsColor) {
+
+  EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), 
"",
+{"-fcolor-diagnostics"}));
+  EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false),
+"", {"-fno-color-diagnostics"}));
+  EXPECT_TRUE(
+  runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "",
+{"-fno-color-diagnostics", 
"-fcolor-diagnostics"}));
+  EXPECT_TRUE(
+  runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "",
+{"-fcolor-diagnostics", 
"-fno-color-diagnostics"}));
+  EXPECT_TRUE(runToolOnCodeWithArgs(
+  new CheckColoredDiagnosticsAction(true), "",
+  {"-fno-color-diagnostics", "-fdiagnostics-color=always"}));
+
+  // Check that this test would fail if ShowColors is not what it should.
+  EXPECT_FALSE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false),
+ "", {"-fcolor-diagnostics"}));
+}
+
 TEST(ClangToolTest, ArgumentAdjusters) {
   FixedCompilationDatabase Compilations("/", std::vector());
 


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


Re: [PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11

2016-08-30 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

ping


https://reviews.llvm.org/D21502



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


Re: [PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11

2016-08-30 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

Ping


https://reviews.llvm.org/D21502



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


Re: [PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11

2016-08-24 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

Ping!


https://reviews.llvm.org/D21502



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


[PATCH] D23837: Fix colored diagnostics from tools

2016-08-24 Thread Olivier Goffart via cfe-commits
ogoffart created this revision.
ogoffart added reviewers: bruno, dexonsmith, cfe-commits.
Herald added a subscriber: klimek.

r271042 changed the way the diagnostic arguments are parsed. It assumes that
the diagnostics options were already parsed by the "Driver".
For tools using clang::Tooling, the diagnostics argument were not parsed.


https://reviews.llvm.org/D23837

Files:
  lib/Tooling/Tooling.cpp

Index: lib/Tooling/Tooling.cpp
===
--- lib/Tooling/Tooling.cpp
+++ lib/Tooling/Tooling.cpp
@@ -15,6 +15,7 @@
 #include "clang/Tooling/Tooling.h"
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
 #include "clang/Driver/Tool.h"
 #include "clang/Driver/ToolChain.h"
 #include "clang/Frontend/ASTUnit.h"
@@ -26,6 +27,7 @@
 #include "clang/Tooling/CompilationDatabase.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/FileSystem.h"
@@ -241,6 +243,9 @@
 Argv.push_back(Str.c_str());
   const char *const BinaryName = Argv[0];
   IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions();
+  unsigned MissingArgIndex, MissingArgCount;
+  llvm::opt::InputArgList ParsedArgs = 
driver::createDriverOptTable()->ParseArgs(ArrayRef(Argv).slice(1), MissingArgIndex, MissingArgCount);
+  ParseDiagnosticArgs(*DiagOpts, ParsedArgs);
   TextDiagnosticPrinter DiagnosticPrinter(
   llvm::errs(), &*DiagOpts);
   DiagnosticsEngine Diagnostics(


Index: lib/Tooling/Tooling.cpp
===
--- lib/Tooling/Tooling.cpp
+++ lib/Tooling/Tooling.cpp
@@ -15,6 +15,7 @@
 #include "clang/Tooling/Tooling.h"
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
 #include "clang/Driver/Tool.h"
 #include "clang/Driver/ToolChain.h"
 #include "clang/Frontend/ASTUnit.h"
@@ -26,6 +27,7 @@
 #include "clang/Tooling/CompilationDatabase.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/FileSystem.h"
@@ -241,6 +243,9 @@
 Argv.push_back(Str.c_str());
   const char *const BinaryName = Argv[0];
   IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions();
+  unsigned MissingArgIndex, MissingArgCount;
+  llvm::opt::InputArgList ParsedArgs = driver::createDriverOptTable()->ParseArgs(ArrayRef(Argv).slice(1), MissingArgIndex, MissingArgCount);
+  ParseDiagnosticArgs(*DiagOpts, ParsedArgs);
   TextDiagnosticPrinter DiagnosticPrinter(
   llvm::errs(), &*DiagOpts);
   DiagnosticsEngine Diagnostics(
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26350: Keep invalid Switch in the AST

2016-11-07 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

I believe only the change in ActOnFinishSwitchStmt might be controversial. 
Is it breaking an invariant than having switches kept in the AST?


https://reviews.llvm.org/D26350



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


[PATCH] D26350: Keep invalid Switch in the AST

2016-11-07 Thread Olivier Goffart via cfe-commits
ogoffart created this revision.
ogoffart added reviewers: rsmith, cfe-commits.

- When the condition is invalid, replace it by an OpaqueValueExpr

- When parsing an invalid CaseStmt, don't drop the sub statement, just return  
it instead.

- In Sema::ActOnStartOfSwitchStmt, always keep the SwitchStmt, even if it has 
duplicate case or defaults statement or that the condition cannot be converted 
to an integral type.




https://reviews.llvm.org/D26350

Files:
  lib/Parse/ParseStmt.cpp
  lib/Sema/SemaStmt.cpp
  test/Misc/ast-dump-invalid-switch.cpp

Index: test/Misc/ast-dump-invalid-switch.cpp
===
--- /dev/null
+++ test/Misc/ast-dump-invalid-switch.cpp
@@ -0,0 +1,105 @@
+// RUN: not %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fms-extensions -ast-dump -ast-dump-filter Test %s | FileCheck -check-prefix CHECK -strict-whitespace %s
+
+/* This test ensures that the AST is still complete, even for invalid code */
+
+namespace TestInvalidSwithCondition {
+int f(int x) {
+  switch (_invalid_) {
+  case 0:
+return 1;
+  default:
+return 2;
+  }
+}
+}
+
+// CHECK: NamespaceDecl {{.*}} TestInvalidSwithCondition
+// CHECK-NEXT: `-FunctionDecl
+// CHECK-NEXT:   |-ParmVarDecl
+// CHECK-NEXT:   `-CompoundStmt
+// CHECK-NEXT: `-SwitchStmt
+// CHECK-NEXT:   |-<<>>
+// CHECK-NEXT:   |-<<>>
+// CHECK-NEXT:   |-OpaqueValueExpr
+// CHECK-NEXT:   `-CompoundStmt
+// CHECK-NEXT: |-CaseStmt
+// CHECK-NEXT: | |-IntegerLiteral {{.*}} 'int' 0
+// CHECK-NEXT: | |-<<>>
+// CHECK-NEXT: | `-ReturnStmt
+// CHECK-NEXT: |   `-IntegerLiteral {{.*}} 'int' 1
+// CHECK-NEXT: `-DefaultStmt
+// CHECK-NEXT:   `-ReturnStmt
+// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 2
+
+namespace TestSwitchConditionNotIntegral {
+int g(int *x) {
+  switch (x) {
+  case 0:
+return 1;
+  default:
+return 2;
+  }
+}
+}
+
+// CHECK: NamespaceDecl {{.*}} TestSwitchConditionNotIntegral
+// CHECK-NEXT: `-FunctionDecl
+// CHECK-NEXT:   |-ParmVarDecl
+// CHECK-NEXT:   `-CompoundStmt
+// CHECK-NEXT: `-SwitchStmt
+// CHECK-NEXT:   |-<<>>
+// CHECK-NEXT:   |-<<>>
+// CHECK-NEXT:   |-ImplicitCastExpr
+// CHECK-NEXT:   | `-DeclRefExpr {{.*}} 'x' 'int *'
+// CHECK-NEXT:   `-CompoundStmt
+// CHECK-NEXT: |-CaseStmt
+// CHECK-NEXT: | |-IntegerLiteral {{.*}} 'int' 0
+// CHECK-NEXT: | |-<<>>
+// CHECK-NEXT: | `-ReturnStmt
+// CHECK-NEXT: |   `-IntegerLiteral {{.*}} 'int' 1
+// CHECK-NEXT: `-DefaultStmt
+// CHECK-NEXT:   `-ReturnStmt
+// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 2
+
+namespace TestSwitchInvalidCases {
+int g(int x) {
+  switch (x) {
+  case _invalid_:
+return 1;
+  case _invalid_:
+return 2;
+  case x:
+return 3;
+  default:
+return 4;
+  default:
+return 5;
+  }
+}
+}
+
+// CHECK: NamespaceDecl {{.*}} TestSwitchInvalidCases
+// CHECK-NEXT: `-FunctionDecl
+// CHECK-NEXT:   |-ParmVarDecl
+// CHECK-NEXT:   `-CompoundStmt
+// CHECK-NEXT: `-SwitchStmt
+// CHECK-NEXT:   |-<<>>
+// CHECK-NEXT:   |-<<>>
+// CHECK-NEXT:   |-ImplicitCastExpr
+// CHECK-NEXT:   | `-DeclRefExpr {{.*}}'x' 'int'
+// CHECK-NEXT:   `-CompoundStmt
+// CHECK-NEXT: |-ReturnStmt
+// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 1
+// CHECK-NEXT: |-ReturnStmt
+// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 2
+// CHECK-NEXT: |-CaseStmt
+// CHECK-NEXT: | |-DeclRefExpr {{.*}} 'x' 'int'
+// CHECK-NEXT: | |-<<>>
+// CHECK-NEXT: | `-ReturnStmt
+// CHECK-NEXT: |   `-IntegerLiteral {{.*}} 'int' 3
+// CHECK-NEXT: |-DefaultStmt
+// CHECK-NEXT: | `-ReturnStmt
+// CHECK-NEXT: |   `-IntegerLiteral {{.*}} 'int' 4
+// CHECK-NEXT: `-DefaultStmt
+// CHECK-NEXT:   `-ReturnStmt
+// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 5
Index: lib/Sema/SemaStmt.cpp
===
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -666,7 +666,12 @@
 StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
 Stmt *InitStmt, ConditionResult Cond) {
   if (Cond.isInvalid())
-return StmtError();
+Cond = ConditionResult(
+*this, nullptr,
+MakeFullExpr(new (Context) OpaqueValueExpr(SourceLocation(),
+   Context.IntTy, VK_RValue),
+ SwitchLoc),
+false);
 
   getCurFunction()->setHasBranchIntoScope();
 
@@ -768,7 +773,7 @@
 // type, when we started the switch statement. If we don't have an
 // appropriate type now, just return an error.
 if (!CondType->isIntegralOrEnumerationType())
-  return StmtError();
+  return SS;
 
 if (CondExpr->isKnownToHaveBooleanValue()) {
   // switch(bool_expr) 

[PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11

2016-10-22 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

Ping?
I guess i coud just commit it now.


https://reviews.llvm.org/D21502



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


[PATCH] D26465: [Diag] Optimize DiagnosticIDs::getDiagnosticSeverity

2016-11-20 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

ping?


https://reviews.llvm.org/D26465



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


[PATCH] D26350: Keep invalid Switch in the AST

2016-11-20 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

ping?


https://reviews.llvm.org/D26350



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


r285883 - Fix heuristics skipping invalid ctor-initializers with C++11

2016-11-03 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Thu Nov  3 02:36:17 2016
New Revision: 285883

URL: http://llvm.org/viewvc/llvm-project?rev=285883=rev
Log:
Fix heuristics skipping invalid ctor-initializers with C++11

Use better heuristics to detect if a '{' might be the start of the constructor 
body
or not. Especially when there is a completion token.

Fix the test 'test/CodeCompletion/ctor-initializer.cpp ' when clang defaults to 
c++11

The problem was is how we recover invalid code in the ctor-init part as we skip 
the
function body. In particular, we want to know if a '{' is the begining of the 
body.
In C++03, we always consider it as the beginng of the body. The problem was 
that in
C++11, it may be the start of an initializer, so we skip over it, causing 
further
parse errors later. (It is important that we are able to parse correctly the 
rest
of the class definition, to know what are the class member, for example)

This commit is improving the heuristics to decide if the '{' is starting a 
function
body. The rules are the following: If we are not in a template argument, and 
that the
previous tokens are not an identifier, or a >, then it is much more likely to 
be the
function body. We verify that further by checking the token after the matching 
'}'

The commit also fix the behavior when there is a code_completion token in the
ctor-initializers.

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

Modified:
cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
cfe/trunk/test/CodeCompletion/ctor-initializer.cpp

Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=285883=285882=285883=diff
==
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Thu Nov  3 02:36:17 2016
@@ -832,22 +832,30 @@ bool Parser::ConsumeAndStoreFunctionProl
 }
   }
 
-  if (Tok.isOneOf(tok::identifier, tok::kw_template)) {
+  if (Tok.is(tok::identifier)) {
 Toks.push_back(Tok);
 ConsumeToken();
-  } else if (Tok.is(tok::code_completion)) {
-Toks.push_back(Tok);
-ConsumeCodeCompletionToken();
-// Consume the rest of the initializers permissively.
-// FIXME: We should be able to perform code-completion here even if
-//there isn't a subsequent '{' token.
-MightBeTemplateArgument = true;
-break;
   } else {
 break;
   }
 } while (Tok.is(tok::coloncolon));
 
+if (Tok.is(tok::code_completion)) {
+  Toks.push_back(Tok);
+  ConsumeCodeCompletionToken();
+  if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype)) {
+// Could be the start of another member initializer (the ',' has not
+// been written yet)
+continue;
+  }
+}
+
+if (Tok.is(tok::comma)) {
+  // The initialization is missing, we'll diagnose it later.
+  Toks.push_back(Tok);
+  ConsumeToken();
+  continue;
+}
 if (Tok.is(tok::less))
   MightBeTemplateArgument = true;
 
@@ -888,6 +896,26 @@ bool Parser::ConsumeAndStoreFunctionProl
   // means the initializer is malformed; we'll diagnose it later.
   if (!getLangOpts().CPlusPlus11)
 return false;
+
+  const Token  = Toks[Toks.size() - 2];
+  if (!MightBeTemplateArgument &&
+  !PreviousToken.isOneOf(tok::identifier, tok::greater,
+ tok::greatergreater)) {
+// If the opening brace is not preceded by one of these tokens, we are
+// missing the mem-initializer-id. In order to recover better, we need
+// to use heuristics to determine if this '{' is most likely the
+// begining of a brace-init-list or the function body.
+// Check the token after the corresponding '}'.
+TentativeParsingAction PA(*this);
+if (SkipUntil(tok::r_brace) &&
+!Tok.isOneOf(tok::comma, tok::ellipsis, tok::l_brace)) {
+  // Consider there was a malformed initializer and this is the start
+  // of the function body. We'll diagnose it later.
+  PA.Revert();
+  return false;
+}
+PA.Revert();
+  }
 }
 
 // Grab the initializer (or the subexpression of the template argument).

Modified: cfe/trunk/test/CodeCompletion/ctor-initializer.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/ctor-initializer.cpp?rev=285883=285882=285883=diff
==
--- cfe/trunk/test/CodeCompletion/ctor-initializer.cpp (original)
+++ cfe/trunk/test/CodeCompletion/ctor-initializer.cpp Thu Nov  3 02:36:17 2016
@@ -1,11 +1,13 @@
 struct Base1 {
   Base1() : {}
-  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:2:12 %s -o - | 
FileCheck -check-prefix=CHECK-CC1 %s
+  // RUN: 

[PATCH] D21502: Fix heuristics skipping invalid ctor-initializers with C++11

2016-11-03 Thread Olivier Goffart via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL285883: Fix heuristics skipping invalid ctor-initializers 
with C++11 (authored by ogoffart).

Changed prior to commit:
  https://reviews.llvm.org/D21502?vs=69223=76819#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D21502

Files:
  cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
  cfe/trunk/test/CodeCompletion/ctor-initializer.cpp

Index: cfe/trunk/test/CodeCompletion/ctor-initializer.cpp
===
--- cfe/trunk/test/CodeCompletion/ctor-initializer.cpp
+++ cfe/trunk/test/CodeCompletion/ctor-initializer.cpp
@@ -1,11 +1,13 @@
 struct Base1 {
   Base1() : {}
-  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
   // CHECK-CC1: COMPLETION: Pattern : member1(<#args#>)
   // CHECK-CC1: COMPLETION: Pattern : member2(<#args#>
 
   Base1(int) : member1(123), {}
-  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:7:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:8:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:8:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
   // CHECK-CC2-NOT: COMPLETION: Pattern : member1(<#args#>)
   // CHECK-CC2: COMPLETION: Pattern : member2(<#args#>
 
@@ -21,21 +23,40 @@
 };
 
 Derived::Derived() : {}
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:25:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:25:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
 // CHECK-CC3: COMPLETION: Pattern : Base1(<#args#>)
 // CHECK-CC3: COMPLETION: Pattern : deriv1(<#args#>)
 
 Derived::Derived(int) try : {
 } catch (...) {
 }
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:28:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:31:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:31:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
 // CHECK-CC4: COMPLETION: Pattern : Base1(<#args#>)
 // CHECK-CC4: COMPLETION: Pattern : deriv1(<#args#>)
 
 Derived::Derived(float) try : Base1(),
 {
 } catch (...) {
 }
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:35:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:39:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:39:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
 // CHECK-CC5-NOT: COMPLETION: Pattern : Base1(<#args#>)
 // CHECK-CC5: COMPLETION: Pattern : deriv1(<#args#>)
+
+struct A {
+  A() : , member2() {}
+  // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:49:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:49:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s
+  // CHECK-CC6: COMPLETION: Pattern : member1(<#args#>
+  int member1, member2;
+};
+
+struct B {
+  B() : member2() {}
+  // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:57:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:57:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
+  // CHECK-CC7: COMPLETION: Pattern : member1(<#args#>
+  int member1, member2;
+};
Index: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
===
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
@@ -832,22 +832,30 @@
 }
   }
 
-  if (Tok.isOneOf(tok::identifier, tok::kw_template)) {
+  if (Tok.is(tok::identifier)) {
 Toks.push_back(Tok);
 ConsumeToken();
-  } else if (Tok.is(tok::code_completion)) {
-Toks.push_back(Tok);
-ConsumeCodeCompletionToken();
-// Consume the rest of the initializers permissively.
-// FIXME: We should be able to perform code-completion here even if
-//there isn't a subsequent '{' token.
-MightBeTemplateArgument = true;
-break;
   } else {
 break;
   }
 } while (Tok.is(tok::coloncolon));
 
+if (Tok.is(tok::code_completion)) {
+  Toks.push_back(Tok);
+  ConsumeCodeCompletionToken();
+  if (Tok.isOneOf(tok::identifier, 

[PATCH] D26285: [index] Expose FriendDecl

2016-11-03 Thread Olivier Goffart via cfe-commits
ogoffart added a comment.

KDevelop bug report: https://bugs.kde.org/show_bug.cgi?id=360509


https://reviews.llvm.org/D26285



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


[PATCH] D26285: [index] Expose FriendDecl

2016-11-03 Thread Olivier Goffart via cfe-commits
ogoffart created this revision.
ogoffart added reviewers: cfe-commits, alexey.klimov.dev, bkramer.

I need to be able to visit friend declarations (the function) for the clang 
based qdoc (documentation parser).

This also fix KDevelop not highlighting friend declarations. (Espetialy 
ennoying when declaring an operator with a body)


https://reviews.llvm.org/D26285

Files:
  include/clang-c/Index.h
  lib/Sema/SemaCodeComplete.cpp
  test/Index/load-classes.cpp
  tools/libclang/CIndex.cpp
  tools/libclang/CursorVisitor.h

Index: tools/libclang/CursorVisitor.h
===
--- tools/libclang/CursorVisitor.h
+++ tools/libclang/CursorVisitor.h
@@ -239,7 +239,8 @@
   bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
   bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
   bool VisitStaticAssertDecl(StaticAssertDecl *D);
-  
+  bool VisitFriendDecl(FriendDecl *D);
+
   // Name visitor
   bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
   bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
Index: tools/libclang/CIndex.cpp
===
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -1249,6 +1249,17 @@
   return false;
 }
 
+bool CursorVisitor::VisitFriendDecl(FriendDecl *D) {
+  if (NamedDecl *FriendD = D->getFriendDecl()) {
+if (Visit(MakeCXCursor(FriendD, TU, RegionOfInterest)))
+  return true;
+  } else if (TypeSourceInfo *TI = D->getFriendType()) {
+if (Visit(TI->getTypeLoc()))
+  return true;
+  }
+  return false;
+}
+
 bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
   switch (Name.getName().getNameKind()) {
   case clang::DeclarationName::Identifier:
@@ -4923,6 +4934,8 @@
   return cxstring::createRef("TypeAliasTemplateDecl");
   case CXCursor_StaticAssert:
   return cxstring::createRef("StaticAssert");
+  case CXCursor_FriendDecl:
+return cxstring::createRef("FriendDecl");
   }
 
   llvm_unreachable("Unhandled CXCursorKind");
Index: test/Index/load-classes.cpp
===
--- test/Index/load-classes.cpp
+++ test/Index/load-classes.cpp
@@ -18,13 +18,18 @@
 
   virtual void virtualMemberFunction();
   virtual void pureVirtualMemberFunction() = 0;
+
+  friend void friendFunction();
+  template 
+  friend void friendFunctionTemplate();
+  friend class F;
 };
 
 X::X(int value) {
 }
 
 // RUN: c-index-test -test-load-source all %s | FileCheck %s
-// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 21:2]
+// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 26:2]
 // CHECK: load-classes.cpp:4:3: CXXConstructor=X:4:3 (converting constructor) Extent=[4:3 - 4:15] [access=public]
 // FIXME: missing TypeRef in the constructor name
 // CHECK: load-classes.cpp:4:9: ParmDecl=value:4:9 (Definition) Extent=[4:5 - 4:14]
@@ -46,7 +51,14 @@
 // CHECK: load-classes.cpp:16:21: TemplateTypeParameter=T:16:21 (Definition) Extent=[16:12 - 16:22] [access=public]
 // CHECK: load-classes.cpp:19:16: CXXMethod=virtualMemberFunction:19:16 (virtual) Extent=[19:3 - 19:39] [access=private]
 // CHECK: load-classes.cpp:20:16: CXXMethod=pureVirtualMemberFunction:20:16 (virtual) (pure) Extent=[20:3 - 20:47] [access=private]
-// CHECK: load-classes.cpp:23:4: CXXConstructor=X:23:4 (Definition) (converting constructor) Extent=[23:1 - 24:2] [access=public]
-// CHECK: load-classes.cpp:23:1: TypeRef=struct X:3:8 Extent=[23:1 - 23:2]
-// CHECK: load-classes.cpp:23:10: ParmDecl=value:23:10 (Definition) Extent=[23:6 - 23:15]
-// CHECK: load-classes.cpp:23:17: CompoundStmt= Extent=[23:17 - 24:2]
+// CHECK: load-classes.cpp:22:15: FriendDecl=:22:15 Extent=[22:3 - 22:31] [access=public]
+// CHECK: load-classes.cpp:22:15: FunctionDecl=friendFunction:22:15 Extent=[22:3 - 22:31] [access=public]
+// CHECK: load-classes.cpp:24:15: FriendDecl=:24:15 Extent=[23:3 - 24:39] [access=public]
+// CHECK: load-classes.cpp:24:15: FunctionTemplate=friendFunctionTemplate:24:15 Extent=[23:3 - 24:39] [access=public]
+// CHECK: load-classes.cpp:23:22: TemplateTypeParameter=T:23:22 (Definition) Extent=[23:13 - 23:23] [access=public]
+// CHECK: load-classes.cpp:25:10: FriendDecl=:25:10 Extent=[25:3 - 25:17] [access=public]
+// CHECK: load-classes.cpp:25:16: TypeRef=class F:25:16 Extent=[25:16 - 25:17]
+// CHECK: load-classes.cpp:28:4: CXXConstructor=X:28:4 (Definition) (converting constructor) Extent=[28:1 - 29:2] [access=public]
+// CHECK: load-classes.cpp:28:1: TypeRef=struct X:3:8 Extent=[28:1 - 28:2]
+// CHECK: load-classes.cpp:28:10: ParmDecl=value:28:10 (Definition) Extent=[28:6 - 28:15]
+// CHECK: load-classes.cpp:28:17: CompoundStmt= Extent=[28:17 - 29:2]
Index: lib/Sema/SemaCodeComplete.cpp
===
--- lib/Sema/SemaCodeComplete.cpp
+++ lib/Sema/SemaCodeComplete.cpp

r285986 - [python bindings] Expose CXCursor_FriendDecl as CursorKind.FRIEND_DECL

2016-11-04 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Fri Nov  4 01:50:59 2016
New Revision: 285986

URL: http://llvm.org/viewvc/llvm-project?rev=285986=rev
Log:
[python bindings] Expose CXCursor_FriendDecl as CursorKind.FRIEND_DECL

CXCursor_FriendDecl was added in r285984

Modified:
cfe/trunk/bindings/python/clang/cindex.py

Modified: cfe/trunk/bindings/python/clang/cindex.py
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/clang/cindex.py?rev=285986=285985=285986=diff
==
--- cfe/trunk/bindings/python/clang/cindex.py (original)
+++ cfe/trunk/bindings/python/clang/cindex.py Fri Nov  4 01:50:59 2016
@@ -1317,6 +1317,8 @@ CursorKind.MODULE_IMPORT_DECL = CursorKi
 CursorKind.TYPE_ALIAS_TEMPLATE_DECL = CursorKind(601)
 # A static_assert or _Static_assert node
 CursorKind.STATIC_ASSERT = CursorKind(602)
+# A friend declaration
+CursorKind.FRIEND_DECL = CursorKind(603)
 
 # A code completion overload candidate.
 CursorKind.OVERLOAD_CANDIDATE = CursorKind(700)


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


[PATCH] D26285: [index] Expose FriendDecl

2016-11-04 Thread Olivier Goffart via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL285984: [index] Expose FriendDecl (authored by ogoffart).

Changed prior to commit:
  https://reviews.llvm.org/D26285?vs=76873=76913#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D26285

Files:
  cfe/trunk/include/clang-c/Index.h
  cfe/trunk/lib/Sema/SemaCodeComplete.cpp
  cfe/trunk/test/Index/load-classes.cpp
  cfe/trunk/tools/libclang/CIndex.cpp
  cfe/trunk/tools/libclang/CursorVisitor.h

Index: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
===
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp
@@ -3100,6 +3100,7 @@
   return CXCursor_ClassTemplatePartialSpecialization;
 case Decl::UsingDirective: return CXCursor_UsingDirective;
 case Decl::StaticAssert:   return CXCursor_StaticAssert;
+case Decl::Friend: return CXCursor_FriendDecl;
 case Decl::TranslationUnit:return CXCursor_TranslationUnit;
   
 case Decl::Using:
Index: cfe/trunk/tools/libclang/CursorVisitor.h
===
--- cfe/trunk/tools/libclang/CursorVisitor.h
+++ cfe/trunk/tools/libclang/CursorVisitor.h
@@ -239,7 +239,8 @@
   bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
   bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
   bool VisitStaticAssertDecl(StaticAssertDecl *D);
-  
+  bool VisitFriendDecl(FriendDecl *D);
+
   // Name visitor
   bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
   bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
Index: cfe/trunk/tools/libclang/CIndex.cpp
===
--- cfe/trunk/tools/libclang/CIndex.cpp
+++ cfe/trunk/tools/libclang/CIndex.cpp
@@ -1249,6 +1249,17 @@
   return false;
 }
 
+bool CursorVisitor::VisitFriendDecl(FriendDecl *D) {
+  if (NamedDecl *FriendD = D->getFriendDecl()) {
+if (Visit(MakeCXCursor(FriendD, TU, RegionOfInterest)))
+  return true;
+  } else if (TypeSourceInfo *TI = D->getFriendType()) {
+if (Visit(TI->getTypeLoc()))
+  return true;
+  }
+  return false;
+}
+
 bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
   switch (Name.getName().getNameKind()) {
   case clang::DeclarationName::Identifier:
@@ -4923,6 +4934,8 @@
   return cxstring::createRef("TypeAliasTemplateDecl");
   case CXCursor_StaticAssert:
   return cxstring::createRef("StaticAssert");
+  case CXCursor_FriendDecl:
+return cxstring::createRef("FriendDecl");
   }
 
   llvm_unreachable("Unhandled CXCursorKind");
Index: cfe/trunk/include/clang-c/Index.h
===
--- cfe/trunk/include/clang-c/Index.h
+++ cfe/trunk/include/clang-c/Index.h
@@ -32,7 +32,7 @@
  * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
  */
 #define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 35
+#define CINDEX_VERSION_MINOR 36
 
 #define CINDEX_VERSION_ENCODE(major, minor) ( \
   ((major) * 1)   \
@@ -2404,8 +2404,12 @@
* \brief A static_assert or _Static_assert node
*/
   CXCursor_StaticAssert  = 602,
+  /**
+   * \brief a friend declaration.
+   */
+  CXCursor_FriendDecl= 603,
   CXCursor_FirstExtraDecl= CXCursor_ModuleImportDecl,
-  CXCursor_LastExtraDecl = CXCursor_StaticAssert,
+  CXCursor_LastExtraDecl = CXCursor_FriendDecl,
 
   /**
* \brief A code completion overload candidate.
Index: cfe/trunk/test/Index/load-classes.cpp
===
--- cfe/trunk/test/Index/load-classes.cpp
+++ cfe/trunk/test/Index/load-classes.cpp
@@ -18,13 +18,18 @@
 
   virtual void virtualMemberFunction();
   virtual void pureVirtualMemberFunction() = 0;
+
+  friend void friendFunction();
+  template 
+  friend void friendFunctionTemplate();
+  friend class F;
 };
 
 X::X(int value) {
 }
 
 // RUN: c-index-test -test-load-source all %s | FileCheck %s
-// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 21:2]
+// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 26:2]
 // CHECK: load-classes.cpp:4:3: CXXConstructor=X:4:3 (converting constructor) Extent=[4:3 - 4:15] [access=public]
 // FIXME: missing TypeRef in the constructor name
 // CHECK: load-classes.cpp:4:9: ParmDecl=value:4:9 (Definition) Extent=[4:5 - 4:14]
@@ -46,7 +51,14 @@
 // CHECK: load-classes.cpp:16:21: TemplateTypeParameter=T:16:21 (Definition) Extent=[16:12 - 16:22] [access=public]
 // CHECK: load-classes.cpp:19:16: CXXMethod=virtualMemberFunction:19:16 (virtual) Extent=[19:3 - 19:39] [access=private]
 // CHECK: load-classes.cpp:20:16: CXXMethod=pureVirtualMemberFunction:20:16 (virtual) (pure) Extent=[20:3 - 20:47] 

r285984 - [index] Expose FriendDecl

2016-11-04 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Fri Nov  4 01:29:27 2016
New Revision: 285984

URL: http://llvm.org/viewvc/llvm-project?rev=285984=rev
Log:
[index] Expose FriendDecl

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

Modified:
cfe/trunk/include/clang-c/Index.h
cfe/trunk/lib/Sema/SemaCodeComplete.cpp
cfe/trunk/test/Index/load-classes.cpp
cfe/trunk/tools/libclang/CIndex.cpp
cfe/trunk/tools/libclang/CursorVisitor.h

Modified: cfe/trunk/include/clang-c/Index.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=285984=285983=285984=diff
==
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Fri Nov  4 01:29:27 2016
@@ -32,7 +32,7 @@
  * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
  */
 #define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 35
+#define CINDEX_VERSION_MINOR 36
 
 #define CINDEX_VERSION_ENCODE(major, minor) ( \
   ((major) * 1)   \
@@ -2404,8 +2404,12 @@ enum CXCursorKind {
* \brief A static_assert or _Static_assert node
*/
   CXCursor_StaticAssert  = 602,
+  /**
+   * \brief a friend declaration.
+   */
+  CXCursor_FriendDecl= 603,
   CXCursor_FirstExtraDecl= CXCursor_ModuleImportDecl,
-  CXCursor_LastExtraDecl = CXCursor_StaticAssert,
+  CXCursor_LastExtraDecl = CXCursor_FriendDecl,
 
   /**
* \brief A code completion overload candidate.

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=285984=285983=285984=diff
==
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Fri Nov  4 01:29:27 2016
@@ -3100,6 +3100,7 @@ CXCursorKind clang::getCursorKindForDecl
   return CXCursor_ClassTemplatePartialSpecialization;
 case Decl::UsingDirective: return CXCursor_UsingDirective;
 case Decl::StaticAssert:   return CXCursor_StaticAssert;
+case Decl::Friend: return CXCursor_FriendDecl;
 case Decl::TranslationUnit:return CXCursor_TranslationUnit;
   
 case Decl::Using:

Modified: cfe/trunk/test/Index/load-classes.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/load-classes.cpp?rev=285984=285983=285984=diff
==
--- cfe/trunk/test/Index/load-classes.cpp (original)
+++ cfe/trunk/test/Index/load-classes.cpp Fri Nov  4 01:29:27 2016
@@ -18,13 +18,18 @@ private:
 
   virtual void virtualMemberFunction();
   virtual void pureVirtualMemberFunction() = 0;
+
+  friend void friendFunction();
+  template 
+  friend void friendFunctionTemplate();
+  friend class F;
 };
 
 X::X(int value) {
 }
 
 // RUN: c-index-test -test-load-source all %s | FileCheck %s
-// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 
21:2]
+// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 
26:2]
 // CHECK: load-classes.cpp:4:3: CXXConstructor=X:4:3 (converting constructor) 
Extent=[4:3 - 4:15] [access=public]
 // FIXME: missing TypeRef in the constructor name
 // CHECK: load-classes.cpp:4:9: ParmDecl=value:4:9 (Definition) Extent=[4:5 - 
4:14]
@@ -46,7 +51,14 @@ X::X(int value) {
 // CHECK: load-classes.cpp:16:21: TemplateTypeParameter=T:16:21 (Definition) 
Extent=[16:12 - 16:22] [access=public]
 // CHECK: load-classes.cpp:19:16: CXXMethod=virtualMemberFunction:19:16 
(virtual) Extent=[19:3 - 19:39] [access=private]
 // CHECK: load-classes.cpp:20:16: CXXMethod=pureVirtualMemberFunction:20:16 
(virtual) (pure) Extent=[20:3 - 20:47] [access=private]
-// CHECK: load-classes.cpp:23:4: CXXConstructor=X:23:4 (Definition) 
(converting constructor) Extent=[23:1 - 24:2] [access=public]
-// CHECK: load-classes.cpp:23:1: TypeRef=struct X:3:8 Extent=[23:1 - 23:2]
-// CHECK: load-classes.cpp:23:10: ParmDecl=value:23:10 (Definition) 
Extent=[23:6 - 23:15]
-// CHECK: load-classes.cpp:23:17: CompoundStmt= Extent=[23:17 - 24:2]
+// CHECK: load-classes.cpp:22:15: FriendDecl=:22:15 Extent=[22:3 - 22:31] 
[access=public]
+// CHECK: load-classes.cpp:22:15: FunctionDecl=friendFunction:22:15 
Extent=[22:3 - 22:31] [access=public]
+// CHECK: load-classes.cpp:24:15: FriendDecl=:24:15 Extent=[23:3 - 24:39] 
[access=public]
+// CHECK: load-classes.cpp:24:15: 
FunctionTemplate=friendFunctionTemplate:24:15 Extent=[23:3 - 24:39] 
[access=public]
+// CHECK: load-classes.cpp:23:22: TemplateTypeParameter=T:23:22 (Definition) 
Extent=[23:13 - 23:23] [access=public]
+// CHECK: load-classes.cpp:25:10: FriendDecl=:25:10 Extent=[25:3 - 25:17] 
[access=public]
+// CHECK: load-classes.cpp:25:16: TypeRef=class F:25:16 Extent=[25:16 - 25:17]
+// CHECK: load-classes.cpp:28:4: 

r285994 - [test] Test that static_assert is properly visited in liblcang

2016-11-04 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Fri Nov  4 07:04:16 2016
New Revision: 285994

URL: http://llvm.org/viewvc/llvm-project?rev=285994=rev
Log:
[test] Test that static_assert is properly visited in liblcang

Added:
cfe/trunk/test/Index/load-staticassert.cpp

Added: cfe/trunk/test/Index/load-staticassert.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/load-staticassert.cpp?rev=285994=auto
==
--- cfe/trunk/test/Index/load-staticassert.cpp (added)
+++ cfe/trunk/test/Index/load-staticassert.cpp Fri Nov  4 07:04:16 2016
@@ -0,0 +1,11 @@
+
+static_assert(2 + 2 == 4, "Simple maths");
+
+// RUN: c-index-test -test-load-source all -fno-delayed-template-parsing 
-std=c++11 %s | FileCheck %s
+// CHECK: load-staticassert.cpp:2:1: StaticAssert=:2:1 (Definition) 
Extent=[2:1 - 2:42]
+// CHECK: load-staticassert.cpp:2:15: BinaryOperator= Extent=[2:15 - 2:25]
+// CHECK: load-staticassert.cpp:2:15: BinaryOperator= Extent=[2:15 - 2:20]
+// CHECK: load-staticassert.cpp:2:15: IntegerLiteral= Extent=[2:15 - 2:16]
+// CHECK: load-staticassert.cpp:2:19: IntegerLiteral= Extent=[2:19 - 2:20]
+// CHECK: load-staticassert.cpp:2:24: IntegerLiteral= Extent=[2:24 - 2:25]
+// CHECK: load-staticassert.cpp:2:27: StringLiteral="Simple maths" 
Extent=[2:27 - 2:41]


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


r307371 - Fix crash parsing invalid code

2017-07-07 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Fri Jul  7 02:38:59 2017
New Revision: 307371

URL: http://llvm.org/viewvc/llvm-project?rev=307371=rev
Log:
Fix crash parsing invalid code

The code in the test caused a crash with this backtrace:

 RecordLayoutBuilder.cpp:2934: const clang::ASTRecordLayout 
::ASTContext::getASTRecordLayout(const clang::RecordDecl *) const: 
Assertion `!D->isInvalidDecl() && "Cannot get layout of invalid decl!"' failed.
 [...]
 #7 0x7f63963d845a __assert_fail_base (/usr/lib/libc.so.6+0x2c45a)
 #8 0x7f63963d84d2 (/usr/lib/libc.so.6+0x2c4d2)
 #9 0x7f63937a0631 clang::ASTContext::getASTRecordLayout(clang::RecordDecl 
const*) const 
/home/olivier/prog/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp:2935:3
 #10 0x7f63937a1ad5 getFieldOffset(clang::ASTContext const&, 
clang::FieldDecl const*) 
/home/olivier/prog/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp:3057:37
 #11 0x7f6391869f14 
clang::Sema::RefersToMemberWithReducedAlignment(clang::Expr*, 
llvm::function_ref) 
/home/olivier/prog/llvm/tools/clang/lib/Sema/SemaChecking.cpp:12139:23
 #12 0x7f639186a2f8 clang::Sema::CheckAddressOfPackedMember(clang::Expr*) 
/home/olivier/prog/llvm/tools/clang/lib/Sema/SemaChecking.cpp:12190:1
 #13 0x7f6391a7a81c 
clang::Sema::CheckAddressOfOperand(clang::ActionResult&, 
clang::SourceLocation) 
/home/olivier/prog/llvm/tools/clang/lib/Sema/SemaExpr.cpp:1:10
 #14 0x7f6391a7f5d2 
clang::Sema::CreateBuiltinUnaryOp(clang::SourceLocation, 
clang::UnaryOperatorKind, clang::Expr*) 
/home/olivier/prog/llvm/tools/clang/lib/Sema/SemaExpr.cpp:11932:18

Fixing by bailing out for invalid classes.

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

Modified:
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/test/Sema/address-packed.c

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=307371=307370=307371=diff
==
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Jul  7 02:38:59 2017
@@ -12097,6 +12097,8 @@ void Sema::RefersToMemberWithReducedAlig
 if (ME->isArrow())
   BaseType = BaseType->getPointeeType();
 RecordDecl *RD = BaseType->getAs()->getDecl();
+if (RD->isInvalidDecl())
+  return;
 
 ValueDecl *MD = ME->getMemberDecl();
 auto *FD = dyn_cast(MD);

Modified: cfe/trunk/test/Sema/address-packed.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/address-packed.c?rev=307371=307370=307371=diff
==
--- cfe/trunk/test/Sema/address-packed.c (original)
+++ cfe/trunk/test/Sema/address-packed.c Fri Jul  7 02:38:59 2017
@@ -329,3 +329,12 @@ void g13(void) {
   uint32_t *p32;
   p32 = [0].x; // no-warning
 }
+
+struct Invalid0 {
+  void *x;
+  struct fwd f; // expected-error {{incomplete type}} expected-note {{forward 
declaration}}
+} __attribute__((packed));
+
+void *g14(struct Invalid0 *ivl) {
+  return &(ivl->x);
+}


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


r308008 - Keep the IdentifierInfo in the Token for alternative operator keyword

2017-07-14 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Fri Jul 14 02:23:40 2017
New Revision: 308008

URL: http://llvm.org/viewvc/llvm-project?rev=308008=rev
Log:
Keep the IdentifierInfo in the Token for alternative operator keyword

The goal of this commit is to fix clang-format so it does not merge tokens when
using the alternative spelling keywords. (eg: "not foo" should not become 
"notfoo")

The problem is that Preprocessor::HandleIdentifier used to drop the identifier 
info
from the token for these keyword. This means the first condition of
TokenAnnotator::spaceRequiredBefore is not met. We could add explicit check for
the spelling in that condition, but I think it is better to keep the 
IdentifierInfo
and handle the operator keyword explicitly when needed. That actually leads to 
simpler
code, and probably slightly more efficient as well.

Another side effect of this change is that __identifier(and) will now work as
one would expect, removing a FIXME from the MicrosoftExtensions.cpp test

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

Modified:
cfe/trunk/include/clang/Basic/IdentifierTable.h
cfe/trunk/lib/Lex/PPDirectives.cpp
cfe/trunk/lib/Lex/PPExpressions.cpp
cfe/trunk/lib/Lex/Preprocessor.cpp
cfe/trunk/test/Parser/MicrosoftExtensions.cpp
cfe/trunk/test/Preprocessor/cxx_oper_keyword.cpp
cfe/trunk/unittests/Format/FormatTest.cpp

Modified: cfe/trunk/include/clang/Basic/IdentifierTable.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/IdentifierTable.h?rev=308008=308007=308008=diff
==
--- cfe/trunk/include/clang/Basic/IdentifierTable.h (original)
+++ cfe/trunk/include/clang/Basic/IdentifierTable.h Fri Jul 14 02:23:40 2017
@@ -272,10 +272,6 @@ public:
   /// this identifier is a C++ alternate representation of an operator.
   void setIsCPlusPlusOperatorKeyword(bool Val = true) {
 IsCPPOperatorKeyword = Val;
-if (Val)
-  NeedsHandleIdentifier = true;
-else
-  RecomputeNeedsHandleIdentifier();
   }
   bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; }
 
@@ -381,10 +377,9 @@ private:
   /// This method is very tied to the definition of HandleIdentifier.  Any
   /// change to it should be reflected here.
   void RecomputeNeedsHandleIdentifier() {
-NeedsHandleIdentifier =
-  (isPoisoned() | hasMacroDefinition() | isCPlusPlusOperatorKeyword() |
-   isExtensionToken() | isFutureCompatKeyword() || isOutOfDate() ||
-   isModulesImport());
+NeedsHandleIdentifier = isPoisoned() || hasMacroDefinition() ||
+isExtensionToken() || isFutureCompatKeyword() ||
+isOutOfDate() || isModulesImport();
   }
 };
 

Modified: cfe/trunk/lib/Lex/PPDirectives.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=308008=308007=308008=diff
==
--- cfe/trunk/lib/Lex/PPDirectives.cpp (original)
+++ cfe/trunk/lib/Lex/PPDirectives.cpp Fri Jul 14 02:23:40 2017
@@ -220,26 +220,18 @@ bool Preprocessor::CheckMacroName(Token
 return Diag(MacroNameTok, diag::err_pp_missing_macro_name);
 
   IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
-  if (!II) {
-bool Invalid = false;
-std::string Spelling = getSpelling(MacroNameTok, );
-if (Invalid)
-  return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
-II = getIdentifierInfo(Spelling);
-
-if (!II->isCPlusPlusOperatorKeyword())
-  return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
+  if (!II)
+return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
 
+  if (II->isCPlusPlusOperatorKeyword()) {
 // C++ 2.5p2: Alternative tokens behave the same as its primary token
 // except for their spellings.
 Diag(MacroNameTok, getLangOpts().MicrosoftExt
? diag::ext_pp_operator_used_as_macro_name
: diag::err_pp_operator_used_as_macro_name)
 << II << MacroNameTok.getKind();
-
 // Allow #defining |and| and friends for Microsoft compatibility or
 // recovery when legacy C headers are included in C++.
-MacroNameTok.setIdentifierInfo(II);
   }
 
   if ((isDefineUndef != MU_Other) && II->getPPKeywordID() == tok::pp_defined) {

Modified: cfe/trunk/lib/Lex/PPExpressions.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPExpressions.cpp?rev=308008=308007=308008=diff
==
--- cfe/trunk/lib/Lex/PPExpressions.cpp (original)
+++ cfe/trunk/lib/Lex/PPExpressions.cpp Fri Jul 14 02:23:40 2017
@@ -237,35 +237,32 @@ static bool EvaluateValue(PPValue 
 PP.setCodeCompletionReached();
 PP.LexNonComment(PeekTok);
   }
-  
-  // If this token's spelling is a pp-identifier, check to see if it is
-  // 'defined' or if it is a macro.  Note that we check here 

r318900 - Do not perform the analysis based warning if the warnings are ignored

2017-11-23 Thread Olivier Goffart via cfe-commits
Author: ogoffart
Date: Thu Nov 23 00:15:22 2017
New Revision: 318900

URL: http://llvm.org/viewvc/llvm-project?rev=318900=rev
Log:
Do not perform the analysis based warning if the warnings are ignored

This saves some cycles when compiling with "-w".

(Also fix a potential crash on invalid code for tools that tries to recover 
from some
errors, because analysis might compute the CFG which crashes if the code 
contains
invalid declaration. This does not happen normally with because we also don't 
perform
these analysis if there was an error.)

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

Modified:
cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
cfe/trunk/unittests/Tooling/ToolingTest.cpp

Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=318900=318899=318900=diff
==
--- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original)
+++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Thu Nov 23 00:15:22 2017
@@ -2080,10 +2080,10 @@ AnalysisBasedWarnings::IssueWarnings(sem
   // time.
   DiagnosticsEngine  = S.getDiagnostics();
 
-  // Do not do any analysis for declarations in system headers if we are
-  // going to just ignore them.
-  if (Diags.getSuppressSystemWarnings() &&
-  S.SourceMgr.isInSystemHeader(D->getLocation()))
+  // Do not do any analysis if we are going to just ignore them.
+  if (Diags.getIgnoreAllWarnings() ||
+  (Diags.getSuppressSystemWarnings() &&
+   S.SourceMgr.isInSystemHeader(D->getLocation(
 return;
 
   // For code in dependent contexts, we'll do this at instantiation time.

Modified: cfe/trunk/unittests/Tooling/ToolingTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/ToolingTest.cpp?rev=318900=318899=318900=diff
==
--- cfe/trunk/unittests/Tooling/ToolingTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/ToolingTest.cpp Thu Nov 23 00:15:22 2017
@@ -564,5 +564,31 @@ TEST(ClangToolTest, InjectDiagnosticCons
 }
 #endif
 
+TEST(runToolOnCode, TestResetDiagnostics) {
+  // This is a tool that resets the diagnostic during the compilation.
+  struct ResetDiagnosticAction : public clang::ASTFrontendAction {
+std::unique_ptr CreateASTConsumer(CompilerInstance ,
+   StringRef) override {
+  struct Consumer : public clang::ASTConsumer {
+bool HandleTopLevelDecl(clang::DeclGroupRef D) override {
+  auto  = (*D.begin())->getASTContext().getDiagnostics();
+  // Ignore any error
+  Diags.Reset();
+  // Disable warnings because computing the CFG might crash.
+  Diags.setIgnoreAllWarnings(true);
+  return true;
+}
+  };
+  return llvm::make_unique();
+}
+  };
+
+  // Should not crash
+  EXPECT_FALSE(
+  runToolOnCode(new ResetDiagnosticAction,
+"struct Foo { Foo(int); ~Foo(); struct Fwd _fwd; };"
+"void func() { long x; Foo f(x); }"));
+}
+
 } // end namespace tooling
 } // end namespace clang


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


[clang] 5baea05 - [SEH] Fix capture of this in lambda functions

2021-03-11 Thread Olivier Goffart via cfe-commits

Author: Olivier Goffart
Date: 2021-03-11T09:12:42+01:00
New Revision: 5baea0560160a693b19022c5d0ba637b6b46b2d8

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

LOG: [SEH] Fix capture of this in lambda functions

Commit 1b04bdc2f3ffaa7a0e1e3dbdc3a0cd08f0b9a4ce added support for
capturing the 'this' pointer in a SEH context (__finally or __except),
But the case in which the 'this' pointer is part of a lambda capture
was not handled properly

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

Added: 


Modified: 
clang/lib/CodeGen/CGException.cpp
clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGException.cpp 
b/clang/lib/CodeGen/CGException.cpp
index 97e2a3a4b69a..5ac037cd9db9 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -1879,8 +1879,24 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction 
,
 setAddrOfLocalVar(VD, Recovered);
 
 if (isa(VD)) {
-  CXXThisValue = Builder.CreateLoad(Recovered, "this");
-  CXXABIThisValue = CXXThisValue;
+  CXXABIThisAlignment = ParentCGF.CXXABIThisAlignment;
+  CXXThisAlignment = ParentCGF.CXXThisAlignment;
+  CXXABIThisValue = Builder.CreateLoad(Recovered, "this");
+  if (ParentCGF.LambdaThisCaptureField) {
+LambdaThisCaptureField = ParentCGF.LambdaThisCaptureField;
+// We are in a lambda function where "this" is captured so the
+// CXXThisValue need to be loaded from the lambda capture
+LValue ThisFieldLValue =
+EmitLValueForLambdaField(LambdaThisCaptureField);
+if (!LambdaThisCaptureField->getType()->isPointerType()) {
+  CXXThisValue = ThisFieldLValue.getAddress(*this).getPointer();
+} else {
+  CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation())
+ .getScalarVal();
+}
+  } else {
+CXXThisValue = CXXABIThisValue;
+  }
 }
   }
 
@@ -1949,6 +1965,7 @@ void 
CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction ,
   StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args,
 OutlinedStmt->getBeginLoc(), OutlinedStmt->getBeginLoc());
   CurSEHParent = ParentCGF.CurSEHParent;
+  CurCodeDecl = ParentCGF.CurCodeDecl;
 
   CGM.SetInternalFunctionAttributes(GlobalDecl(), CurFn, FnInfo);
   EmitCapturedLocals(ParentCGF, OutlinedStmt, IsFilter);

diff  --git a/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp 
b/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
index f6cca8eda9d9..6b5c27097cbd 100644
--- a/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
+++ b/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
@@ -123,3 +123,25 @@ void test_lambda() {
 // CHECK: %[[l1_ref:[^ ]*]] = load i32*, i32** %[[l1_ref_ptr]]
 // CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ref]]
 // CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l1]], i32 %[[l2]])
+
+struct U {
+  void this_in_lambda();
+};
+
+void U::this_in_lambda() {
+  auto lambda = [=]() {
+__try {
+  might_crash();
+} __except (basic_filter(0, this)) {
+}
+  };
+  lambda();
+}
+
+// CHECK-LABEL: define internal i32 
@"?filt$0@0@?R@?0??this_in_lambda@U@@QEAAXXZ@"(i8* 
%exception_pointers, i8* %frame_pointer)
+// CHECK: %[[this_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void 
(%class.anon.0*)* @"??R@?0??this_in_lambda@U@@QEAAXXZ@QEBA@XZ" to 
i8*), i8* %[[fp:[^ ]*]], i32 0)
+// CHECK: %[[this_ptr:[^ ]*]] = bitcast i8* %[[this_i8]] to %class.anon.0**
+// CHECK: %[[this:[^ ]*]] = load %class.anon.0*, %class.anon.0** 
%[[this_ptr]], align 8
+// CHECK: %[[actual_this_ptr:[^ ]*]] = getelementptr inbounds %class.anon.0, 
%class.anon.0* %[[this]], i32 0, i32 0
+// CHECK: %[[actual_this:[^ ]*]] = load %struct.U*, %struct.U** 
%[[actual_this_ptr]], align 8
+// CHECK: call i32 (i32, ...) @basic_filter(i32 0, %struct.U* %[[actual_this]])



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


[clang] 1b04bdc - [SEH] capture 'this'

2021-03-01 Thread Olivier Goffart via cfe-commits

Author: Olivier Goffart
Date: 2021-03-01T11:57:35+01:00
New Revision: 1b04bdc2f3ffaa7a0e1e3dbdc3a0cd08f0b9a4ce

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

LOG: [SEH] capture 'this'

Simply make sure that the CodeGenFunction::CXXThisValue and CXXABIThisValue
are correctly initialized to the recovered value.
For lambda capture, we also need to make sure to fill the LambdaCaptureFields

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

Added: 


Modified: 
clang/lib/CodeGen/CGException.cpp
clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGException.cpp 
b/clang/lib/CodeGen/CGException.cpp
index 7a64963183bc..ce8b42a8c63f 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -1702,10 +1702,8 @@ struct CaptureFinder : ConstStmtVisitor {
 
   void VisitDeclRefExpr(const DeclRefExpr *E) {
 // If this is already a capture, just make sure we capture 'this'.
-if (E->refersToEnclosingVariableOrCapture()) {
+if (E->refersToEnclosingVariableOrCapture())
   Captures.insert(ParentThis);
-  return;
-}
 
 const auto *D = dyn_cast(E->getDecl());
 if (D && D->isLocalVarDeclOrParm() && D->hasLocalStorage())
@@ -1865,11 +1863,6 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction 
,
 
   // Create llvm.localrecover calls for all captures.
   for (const VarDecl *VD : Finder.Captures) {
-if (isa(VD)) {
-  CGM.ErrorUnsupported(VD, "'this' captured by SEH");
-  CXXThisValue = llvm::UndefValue::get(ConvertTypeForMem(VD->getType()));
-  continue;
-}
 if (VD->getType()->isVariablyModifiedType()) {
   CGM.ErrorUnsupported(VD, "VLA captured by SEH");
   continue;
@@ -1877,6 +1870,12 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction 
,
 assert((isa(VD) || VD->isLocalVarDeclOrParm()) &&
"captured non-local variable");
 
+auto L = ParentCGF.LambdaCaptureFields.find(VD);
+if (L != ParentCGF.LambdaCaptureFields.end()) {
+  LambdaCaptureFields[VD] = L->second;
+  continue;
+}
+
 // If this decl hasn't been declared yet, it will be declared in the
 // OutlinedStmt.
 auto I = ParentCGF.LocalDeclMap.find(VD);
@@ -1884,8 +1883,14 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction 
,
   continue;
 
 Address ParentVar = I->second;
-setAddrOfLocalVar(
-VD, recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP));
+Address Recovered =
+recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP);
+setAddrOfLocalVar(VD, Recovered);
+
+if (isa(VD)) {
+  CXXThisValue = Builder.CreateLoad(Recovered, "this");
+  CXXABIThisValue = CXXThisValue;
+}
   }
 
   if (Finder.SEHCodeSlot.isValid()) {

diff  --git a/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp 
b/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
index ac33dbff0b1c..f6cca8eda9d9 100644
--- a/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
+++ b/clang/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
@@ -39,13 +39,13 @@ void S::test_method() {
   int l1 = 13;
   __try {
 might_crash();
-  } __except(basic_filter(l1)) {
-// FIXME: Test capturing 'this' and 'm1'.
+  } __except (basic_filter(l1, m1)) {
   }
 }
 
 // CHECK-LABEL: define dso_local void @"?test_method@S@@QEAAXXZ"(%struct.S* 
{{[^,]*}} %this)
-// CHECK: @llvm.localescape(i32* %[[l1_addr:[^, ]*]])
+// CHECK: @llvm.localescape(i32* %[[l1_addr:[^, ]*]], %struct.S** 
%[[this_addr:[^, ]*]])
+// CHECK: store %struct.S* %this, %struct.S** %[[this_addr]], align 8
 // CHECK: store i32 13, i32* %[[l1_addr]], align 4
 // CHECK: invoke void @might_crash()
 
@@ -53,8 +53,45 @@ void S::test_method() {
 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void 
(%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer)
 // CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void 
(%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0)
 // CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
+// CHECK: %[[this_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void 
(%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 1)
+// CHECK: %[[this_ptr:[^ ]*]] = bitcast i8* %[[this_i8]] to %struct.S**
+// CHECK: %[[this:[^ ]*]] = load %struct.S*, %struct.S** %[[this_ptr]], align 8
+// CHECK: %[[m1_ptr:[^ ]*]] = getelementptr inbounds %struct.S, %struct.S* 
%[[this]], i32 0, i32 0
+// CHECK: %[[m1:[^ ]*]] = load i32, i32* %[[m1_ptr]]
 // CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
-// CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l1]])
+// CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l1]], i32 %[[m1]])
+
+struct V {
+