[PATCH] D27700: [clang-tidy] refactor ExprSequence out of misc-use-after-move check

2016-12-24 Thread Marek SokoĊ‚owski via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL290489: [clang-tidy] refactor ExprSequence out of 
use-after-move check (authored by mnbvmar).

Changed prior to commit:
  https://reviews.llvm.org/D27700?vs=81732&id=82440#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D27700

Files:
  clang-tools-extra/trunk/clang-tidy/misc/UseAfterMoveCheck.cpp
  clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt
  clang-tools-extra/trunk/clang-tidy/utils/ExprSequence.cpp
  clang-tools-extra/trunk/clang-tidy/utils/ExprSequence.h

Index: clang-tools-extra/trunk/clang-tidy/utils/ExprSequence.h
===
--- clang-tools-extra/trunk/clang-tidy/utils/ExprSequence.h
+++ clang-tools-extra/trunk/clang-tidy/utils/ExprSequence.h
@@ -0,0 +1,124 @@
+//===- ExprSequence.h - clang-tidy ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_EXPRSEQUENCE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_EXPRSEQUENCE_H
+
+#include "clang/Analysis/CFG.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+/// Provides information about the evaluation order of (sub-)expressions within
+/// a `CFGBlock`.
+///
+/// While a `CFGBlock` does contain individual `CFGElement`s for some
+/// sub-expressions, the order in which those `CFGElement`s appear reflects
+/// only one possible order in which the sub-expressions may be evaluated.
+/// However, we want to warn if any of the potential evaluation orders can lead
+/// to a use-after-move, not just the one contained in the `CFGBlock`.
+///
+/// This class implements only a simplified version of the C++ sequencing
+/// rules. The main limitation is that we do not distinguish between value
+/// computation and side effect -- see the "Implementation" section for more
+/// details.
+///
+/// Note: `SequenceChecker` from SemaChecking.cpp does a similar job (and much
+/// more thoroughly), but using it would require
+/// - Pulling `SequenceChecker` out into a header file (i.e. making it part of
+///   the API),
+/// - Removing the dependency of `SequenceChecker` on `Sema`, and
+/// - (Probably) modifying `SequenceChecker` to make it suitable to be used in
+///   this context.
+/// For the moment, it seems preferable to re-implement our own version of
+/// sequence checking that is special-cased to what we need here.
+///
+/// Implementation
+/// --
+///
+/// `ExprSequence` uses two types of sequencing edges between nodes in the AST:
+///
+/// - Every `Stmt` is assumed to be sequenced after its children. This is
+///   overly optimistic because the standard only states that value computations
+///   of operands are sequenced before the value computation of the operator,
+///   making no guarantees about side effects (in general).
+///
+///   For our purposes, this rule is sufficient, however, because this check is
+///   interested in operations on objects, which are generally performed through
+///   function calls (whether explicit and implicit). Function calls guarantee
+///   that the value computations and side effects for all function arguments
+///   are sequenced before the execution of the function.
+///
+/// - In addition, some `Stmt`s are known to be sequenced before or after
+///   their siblings. For example, the `Stmt`s that make up a `CompoundStmt`are
+///   all sequenced relative to each other. The function
+///   `getSequenceSuccessor()` implements these sequencing rules.
+class ExprSequence {
+public:
+  /// Initializes this `ExprSequence` with sequence information for the given
+  /// `CFG`.
+  ExprSequence(const CFG *TheCFG, ASTContext *TheContext);
+
+  /// Returns whether \p Before is sequenced before \p After.
+  bool inSequence(const Stmt *Before, const Stmt *After) const;
+
+  /// Returns whether \p After can potentially be evaluated after \p Before.
+  /// This is exactly equivalent to `!inSequence(After, Before)` but makes some
+  /// conditions read more naturally.
+  bool potentiallyAfter(const Stmt *After, const Stmt *Before) const;
+
+private:
+  // Returns the sibling of \p S (if any) that is directly sequenced after \p S,
+  // or nullptr if no such sibling exists. For example, if \p S is the child of
+  // a `CompoundStmt`, this would return the Stmt that directly follows \p S in
+  // the `CompoundStmt`.
+  //
+  // As the sequencing of many constructs that change control flow is already
+  // encoded in the `CFG`, this function only implements the sequencing rules
+  // for those constru

[clang-tools-extra] r290489 - [clang-tidy] refactor ExprSequence out of use-after-move check

2016-12-24 Thread Marek Sokolowski via cfe-commits
Author: mnbvmar
Date: Sat Dec 24 06:45:07 2016
New Revision: 290489

URL: http://llvm.org/viewvc/llvm-project?rev=290489&view=rev
Log:
[clang-tidy] refactor ExprSequence out of use-after-move check

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

Added:
clang-tools-extra/trunk/clang-tidy/utils/ExprSequence.cpp
clang-tools-extra/trunk/clang-tidy/utils/ExprSequence.h
Modified:
clang-tools-extra/trunk/clang-tidy/misc/UseAfterMoveCheck.cpp
clang-tools-extra/trunk/clang-tidy/utils/CMakeLists.txt

Modified: clang-tools-extra/trunk/clang-tidy/misc/UseAfterMoveCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/UseAfterMoveCheck.cpp?rev=290489&r1=290488&r2=290489&view=diff
==
--- clang-tools-extra/trunk/clang-tidy/misc/UseAfterMoveCheck.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/misc/UseAfterMoveCheck.cpp Sat Dec 24 
06:45:07 2016
@@ -11,13 +11,12 @@
 
 #include "clang/Analysis/CFG.h"
 #include "clang/Lex/Lexer.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallVector.h"
 
-#include 
+#include "../utils/ExprSequence.h"
 
 using namespace clang::ast_matchers;
+using namespace clang::tidy::utils;
+
 
 namespace clang {
 namespace tidy {
@@ -25,101 +24,6 @@ namespace misc {
 
 namespace {
 
-/// Provides information about the evaluation order of (sub-)expressions within
-/// a `CFGBlock`.
-///
-/// While a `CFGBlock` does contain individual `CFGElement`s for some
-/// sub-expressions, the order in which those `CFGElement`s appear reflects
-/// only one possible order in which the sub-expressions may be evaluated.
-/// However, we want to warn if any of the potential evaluation orders can lead
-/// to a use-after-move, not just the one contained in the `CFGBlock`.
-///
-/// This class implements only a simplified version of the C++ sequencing rules
-/// that is, however, sufficient for the purposes of this check. The main
-/// limitation is that we do not distinguish between value computation and side
-/// effect -- see the "Implementation" section for more details.
-///
-/// Note: `SequenceChecker` from SemaChecking.cpp does a similar job (and much
-/// more thoroughly), but using it would require
-/// - Pulling `SequenceChecker` out into a header file (i.e. making it part of
-///   the API),
-/// - Removing the dependency of `SequenceChecker` on `Sema`, and
-/// - (Probably) modifying `SequenceChecker` to make it suitable to be used in
-///   this context.
-/// For the moment, it seems preferable to re-implement our own version of
-/// sequence checking that is special-cased to what we need here.
-///
-/// Implementation
-/// --
-///
-/// `ExprSequence` uses two types of sequencing edges between nodes in the AST:
-///
-/// - Every `Stmt` is assumed to be sequenced after its children. This is
-///   overly optimistic because the standard only states that value 
computations
-///   of operands are sequenced before the value computation of the operator,
-///   making no guarantees about side effects (in general).
-///
-///   For our purposes, this rule is sufficient, however, because this check is
-///   interested in operations on objects, which are generally performed 
through
-///   function calls (whether explicit and implicit). Function calls guarantee
-///   that the value computations and side effects for all function arguments
-///   are sequenced before the execution fo the function.
-///
-/// - In addition, some `Stmt`s are known to be sequenced before or after
-///   their siblings. For example, the `Stmt`s that make up a `CompoundStmt`are
-///   all sequenced relative to each other. The function
-///   `getSequenceSuccessor()` implements these sequencing rules.
-class ExprSequence {
-public:
-  /// Initializes this `ExprSequence` with sequence information for the given
-  /// `CFG`.
-  ExprSequence(const CFG *TheCFG, ASTContext *TheContext);
-
-  /// Returns whether \p Before is sequenced before \p After.
-  bool inSequence(const Stmt *Before, const Stmt *After) const;
-
-  /// Returns whether \p After can potentially be evaluated after \p Before.
-  /// This is exactly equivalent to `!inSequence(After, Before)` but makes some
-  /// conditions read more naturally.
-  bool potentiallyAfter(const Stmt *After, const Stmt *Before) const;
-
-private:
-  // Returns the sibling of \p S (if any) that is directly sequenced after \p 
S,
-  // or nullptr if no such sibling exists. For example, if \p S is the child of
-  // a `CompoundStmt`, this would return the Stmt that directly follows \p S in
-  // the `CompoundStmt`.
-  //
-  // As the sequencing of many constructs that change control flow is already
-  // encoded in the `CFG`, this function only implements the sequencing rules
-  // for those constructs where sequencing cannot be inferred from the `CFG`.
-  const Stmt *getSequenceSuccessor(const Stmt *S) con

r290491 - [ASTMatchers] Fix doc for hasBitWidth

2016-12-24 Thread Malcolm Parsons via cfe-commits
Author: malcolm.parsons
Date: Sat Dec 24 07:22:26 2016
New Revision: 290491

URL: http://llvm.org/viewvc/llvm-project?rev=290491&view=rev
Log:
[ASTMatchers] Fix doc for hasBitWidth

Modified:
cfe/trunk/docs/LibASTMatchersReference.html
cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h

Modified: cfe/trunk/docs/LibASTMatchersReference.html
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=290491&r1=290490&r2=290491&view=diff
==
--- cfe/trunk/docs/LibASTMatchersReference.html (original)
+++ cfe/trunk/docs/LibASTMatchersReference.html Sat Dec 24 07:22:26 2016
@@ -2430,7 +2430,8 @@ designatorCountIs(2)
 
 
 MatcherFieldDecl>hasBitWidthunsigned Width
-Matches non-static data 
members that are bit-fields.
+Matches non-static data 
members that are bit-fields of the specified
+bit width.
 
 Given
   class C {
@@ -2438,7 +2439,7 @@ Given
 int b : 4;
 int c : 2;
   };
-fieldDecl(isBitField())
+fieldDecl(hasBitWidth(2))
   matches 'int a;' and 'int c;' but not 'int b;'.
 
 

Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=290491&r1=290490&r2=290491&view=diff
==
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Sat Dec 24 07:22:26 2016
@@ -533,7 +533,8 @@ AST_MATCHER(FieldDecl, isBitField) {
   return Node.isBitField();
 }
 
-/// \brief Matches non-static data members that are bit-fields.
+/// \brief Matches non-static data members that are bit-fields of the specified
+/// bit width.
 ///
 /// Given
 /// \code
@@ -543,7 +544,7 @@ AST_MATCHER(FieldDecl, isBitField) {
 /// int c : 2;
 ///   };
 /// \endcode
-/// fieldDecl(isBitField())
+/// fieldDecl(hasBitWidth(2))
 ///   matches 'int a;' and 'int c;' but not 'int b;'.
 AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width) {
   return Node.isBitField() &&


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


[PATCH] D28034: [ASTMatchers] Add hasInClassInitializer traversal matcher for FieldDecl.

2016-12-24 Thread Malcolm Parsons via Phabricator via cfe-commits
malcolm.parsons updated this revision to Diff 82441.
malcolm.parsons added a comment.

Improve doc.


https://reviews.llvm.org/D28034

Files:
  docs/LibASTMatchersReference.html
  include/clang/ASTMatchers/ASTMatchers.h
  lib/ASTMatchers/Dynamic/Registry.cpp
  unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp


Index: unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1404,6 +1404,16 @@
   fieldDecl(isBitField(), hasBitWidth(2), hasName("a";
 }
 
+TEST(Member, InClassInitializer) {
+  EXPECT_TRUE(
+  matches("class C { int a = 2; int b; };",
+  fieldDecl(hasInClassInitializer(integerLiteral(equals(2))),
+hasName("a";
+  EXPECT_TRUE(
+  notMatches("class C { int a = 2; int b; };",
+ fieldDecl(hasInClassInitializer(anything()), hasName("b";
+}
+
 TEST(Member, UnderstandsAccess) {
   EXPECT_TRUE(matches(
 "struct A { int i; };", fieldDecl(isPublic(), hasName("i";
Index: lib/ASTMatchers/Dynamic/Registry.cpp
===
--- lib/ASTMatchers/Dynamic/Registry.cpp
+++ lib/ASTMatchers/Dynamic/Registry.cpp
@@ -232,6 +232,7 @@
   REGISTER_MATCHER(hasFalseExpression);
   REGISTER_MATCHER(hasGlobalStorage);
   REGISTER_MATCHER(hasImplicitDestinationType);
+  REGISTER_MATCHER(hasInClassInitializer);
   REGISTER_MATCHER(hasIncrement);
   REGISTER_MATCHER(hasIndex);
   REGISTER_MATCHER(hasInitializer);
Index: include/clang/ASTMatchers/ASTMatchers.h
===
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -551,6 +551,27 @@
  Node.getBitWidthValue(Finder->getASTContext()) == Width;
 }
 
+/// \brief Matches non-static data members that have an in-class initializer.
+///
+/// Given
+/// \code
+///   class C {
+/// int a = 2;
+/// int b = 3;
+/// int c;
+///   };
+/// \endcode
+/// fieldDecl(hasInClassInitializer(integerLiteral(equals(2
+///   matches 'int a;' but not 'int b;'.
+/// fieldDecl(hasInClassInitializer(anything()))
+///   matches 'int a;' and 'int b;' but not 'int c;'.
+AST_MATCHER_P(FieldDecl, hasInClassInitializer, internal::Matcher,
+  InnerMatcher) {
+  const Expr *Initializer = Node.getInClassInitializer();
+  return (Initializer != nullptr &&
+  InnerMatcher.matches(*Initializer, Finder, Builder));
+}
+
 /// \brief Matches a declaration that has been implicitly added
 /// by the compiler (eg. implicit default/copy constructors).
 AST_MATCHER(Decl, isImplicit) {
Index: docs/LibASTMatchersReference.html
===
--- docs/LibASTMatchersReference.html
+++ docs/LibASTMatchersReference.html
@@ -4751,6 +4751,22 @@
 
 
 
+MatcherFieldDecl>hasInClassInitializerMatcherExpr> 
InnerMatcher
+Matches 
non-static data members that have an in-class initializer.
+
+Given
+  class C {
+int a = 2;
+int b = 3;
+int c;
+  };
+fieldDecl(hasInClassInitializer(integerLiteral(equals(2
+  matches 'int a;' but not 'int b;'.
+fieldDecl(hasInClassInitializer(anything()))
+  matches 'int a;' and 'int b;' but not 'int c;'.
+
+
+
 MatcherForStmt>hasBodyMatcherStmt> 
InnerMatcher
 Matches a 'for', 'while', 
'do while' statement or a function
 definition that has a given body.


Index: unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1404,6 +1404,16 @@
   fieldDecl(isBitField(), hasBitWidth(2), hasName("a";
 }
 
+TEST(Member, InClassInitializer) {
+  EXPECT_TRUE(
+  matches("class C { int a = 2; int b; };",
+  fieldDecl(hasInClassInitializer(integerLiteral(equals(2))),
+hasName("a";
+  EXPECT_TRUE(
+  notMatches("class C { int a = 2; int b; };",
+ fieldDecl(hasInClassInitializer(anything()), hasName("b";
+}
+
 TEST(Member, UnderstandsAccess) {
   EXPECT_TRUE(matches(
 "struct A { int i; };", fieldDecl(isPublic(), hasName("i";
Index: lib/ASTMatchers/Dynamic/Registry.cpp
===
--- lib/ASTMatchers/Dynamic/Registry.cpp
+++ lib/ASTMatchers/Dynamic/Registry.cpp
@@ -232,6 +232,7 @@
   REGISTER_MATCHER(hasFalseExpression);
   REGISTER_MATCHER(hasGlobalStorage);
   REGISTER_MATCHER(hasImplicitDestinationType);
+  REGISTER_MATCHER(ha

r290492 - [ASTMatchers] Add hasInClassInitializer traversal matcher for FieldDecl.

2016-12-24 Thread Malcolm Parsons via cfe-commits
Author: malcolm.parsons
Date: Sat Dec 24 07:35:14 2016
New Revision: 290492

URL: http://llvm.org/viewvc/llvm-project?rev=290492&view=rev
Log:
[ASTMatchers] Add hasInClassInitializer traversal matcher for FieldDecl.

Summary:
I needed to know whether a FieldDecl had an in-class
initializer for D26453. I used a narrowing matcher there, but a
traversal matcher might be generally useful.

Reviewers: sbenza, bkramer, klimek, aaron.ballman

Subscribers: aaron.ballman, Prazek, cfe-commits

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

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

Modified: cfe/trunk/docs/LibASTMatchersReference.html
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=290492&r1=290491&r2=290492&view=diff
==
--- cfe/trunk/docs/LibASTMatchersReference.html (original)
+++ cfe/trunk/docs/LibASTMatchersReference.html Sat Dec 24 07:35:14 2016
@@ -4751,6 +4751,22 @@ would only match the declaration for a.
 
 
 
+MatcherFieldDecl>hasInClassInitializerMatcherExpr> 
InnerMatcher
+Matches 
non-static data members that have an in-class initializer.
+
+Given
+  class C {
+int a = 2;
+int b = 3;
+int c;
+  };
+fieldDecl(hasInClassInitializer(integerLiteral(equals(2
+  matches 'int a;' but not 'int b;'.
+fieldDecl(hasInClassInitializer(anything()))
+  matches 'int a;' and 'int b;' but not 'int c;'.
+
+
+
 MatcherForStmt>hasBodyMatcherStmt> 
InnerMatcher
 Matches a 'for', 'while', 
'do while' statement or a function
 definition that has a given body.

Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=290492&r1=290491&r2=290492&view=diff
==
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Sat Dec 24 07:35:14 2016
@@ -551,6 +551,27 @@ AST_MATCHER_P(FieldDecl, hasBitWidth, un
  Node.getBitWidthValue(Finder->getASTContext()) == Width;
 }
 
+/// \brief Matches non-static data members that have an in-class initializer.
+///
+/// Given
+/// \code
+///   class C {
+/// int a = 2;
+/// int b = 3;
+/// int c;
+///   };
+/// \endcode
+/// fieldDecl(hasInClassInitializer(integerLiteral(equals(2
+///   matches 'int a;' but not 'int b;'.
+/// fieldDecl(hasInClassInitializer(anything()))
+///   matches 'int a;' and 'int b;' but not 'int c;'.
+AST_MATCHER_P(FieldDecl, hasInClassInitializer, internal::Matcher,
+  InnerMatcher) {
+  const Expr *Initializer = Node.getInClassInitializer();
+  return (Initializer != nullptr &&
+  InnerMatcher.matches(*Initializer, Finder, Builder));
+}
+
 /// \brief Matches a declaration that has been implicitly added
 /// by the compiler (eg. implicit default/copy constructors).
 AST_MATCHER(Decl, isImplicit) {

Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=290492&r1=290491&r2=290492&view=diff
==
--- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Sat Dec 24 07:35:14 2016
@@ -232,6 +232,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(hasFalseExpression);
   REGISTER_MATCHER(hasGlobalStorage);
   REGISTER_MATCHER(hasImplicitDestinationType);
+  REGISTER_MATCHER(hasInClassInitializer);
   REGISTER_MATCHER(hasIncrement);
   REGISTER_MATCHER(hasIndex);
   REGISTER_MATCHER(hasInitializer);

Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp?rev=290492&r1=290491&r2=290492&view=diff
==
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Sat Dec 24 
07:35:14 2016
@@ -1404,6 +1404,16 @@ TEST(Member, BitFields) {
   fieldDecl(isBitField(), hasBitWidth(2), hasName("a";
 }
 
+TEST(Member, InClassInitializer) {
+  EXPECT_TRUE(
+  matches("class C { int a = 2; int b; };",
+  fieldDecl(hasInClassInitializer(integerLiteral(equals(2))),
+hasName("a";
+  EXPECT_TRUE(
+  notMatches

[PATCH] D28034: [ASTMatchers] Add hasInClassInitializer traversal matcher for FieldDecl.

2016-12-24 Thread Malcolm Parsons via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL290492: [ASTMatchers] Add hasInClassInitializer traversal 
matcher for FieldDecl. (authored by malcolm.parsons).

Changed prior to commit:
  https://reviews.llvm.org/D28034?vs=82441&id=82442#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D28034

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


Index: cfe/trunk/docs/LibASTMatchersReference.html
===
--- cfe/trunk/docs/LibASTMatchersReference.html
+++ cfe/trunk/docs/LibASTMatchersReference.html
@@ -4751,6 +4751,22 @@
 
 
 
+MatcherFieldDecl>hasInClassInitializerMatcherExpr> 
InnerMatcher
+Matches 
non-static data members that have an in-class initializer.
+
+Given
+  class C {
+int a = 2;
+int b = 3;
+int c;
+  };
+fieldDecl(hasInClassInitializer(integerLiteral(equals(2
+  matches 'int a;' but not 'int b;'.
+fieldDecl(hasInClassInitializer(anything()))
+  matches 'int a;' and 'int b;' but not 'int c;'.
+
+
+
 MatcherForStmt>hasBodyMatcherStmt> 
InnerMatcher
 Matches a 'for', 'while', 
'do while' statement or a function
 definition that has a given body.
Index: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
===
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
@@ -551,6 +551,27 @@
  Node.getBitWidthValue(Finder->getASTContext()) == Width;
 }
 
+/// \brief Matches non-static data members that have an in-class initializer.
+///
+/// Given
+/// \code
+///   class C {
+/// int a = 2;
+/// int b = 3;
+/// int c;
+///   };
+/// \endcode
+/// fieldDecl(hasInClassInitializer(integerLiteral(equals(2
+///   matches 'int a;' but not 'int b;'.
+/// fieldDecl(hasInClassInitializer(anything()))
+///   matches 'int a;' and 'int b;' but not 'int c;'.
+AST_MATCHER_P(FieldDecl, hasInClassInitializer, internal::Matcher,
+  InnerMatcher) {
+  const Expr *Initializer = Node.getInClassInitializer();
+  return (Initializer != nullptr &&
+  InnerMatcher.matches(*Initializer, Finder, Builder));
+}
+
 /// \brief Matches a declaration that has been implicitly added
 /// by the compiler (eg. implicit default/copy constructors).
 AST_MATCHER(Decl, isImplicit) {
Index: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
===
--- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -232,6 +232,7 @@
   REGISTER_MATCHER(hasFalseExpression);
   REGISTER_MATCHER(hasGlobalStorage);
   REGISTER_MATCHER(hasImplicitDestinationType);
+  REGISTER_MATCHER(hasInClassInitializer);
   REGISTER_MATCHER(hasIncrement);
   REGISTER_MATCHER(hasIndex);
   REGISTER_MATCHER(hasInitializer);
Index: cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1404,6 +1404,16 @@
   fieldDecl(isBitField(), hasBitWidth(2), hasName("a";
 }
 
+TEST(Member, InClassInitializer) {
+  EXPECT_TRUE(
+  matches("class C { int a = 2; int b; };",
+  fieldDecl(hasInClassInitializer(integerLiteral(equals(2))),
+hasName("a";
+  EXPECT_TRUE(
+  notMatches("class C { int a = 2; int b; };",
+ fieldDecl(hasInClassInitializer(anything()), hasName("b";
+}
+
 TEST(Member, UnderstandsAccess) {
   EXPECT_TRUE(matches(
 "struct A { int i; };", fieldDecl(isPublic(), hasName("i";


Index: cfe/trunk/docs/LibASTMatchersReference.html
===
--- cfe/trunk/docs/LibASTMatchersReference.html
+++ cfe/trunk/docs/LibASTMatchersReference.html
@@ -4751,6 +4751,22 @@
 
 
 
+MatcherFieldDecl>hasInClassInitializerMatcherExpr> InnerMatcher
+Matches non-static data members that have an in-class initializer.
+
+Given
+  class C {
+int a = 2;
+int b = 3;
+int c;
+  };
+fieldDecl(hasInClassInitializer(integerLiteral(equals(2
+  matches 'int a;' but not 'int b;'.
+fieldDecl(hasInClassInitializer(anything()))
+  matches 'int a;' and 'int b;' but not 'int c;'.
+
+
+
 Matcher

[PATCH] D28022: [clang-tidy] Handle constructors in performance-unnecessary-value-param

2016-12-24 Thread Malcolm Parsons via Phabricator via cfe-commits
malcolm.parsons updated this revision to Diff 82443.
malcolm.parsons added a comment.

Add double backticks.


https://reviews.llvm.org/D28022

Files:
  clang-tidy/performance/UnnecessaryValueParamCheck.cpp
  clang-tidy/utils/DeclRefExprUtils.cpp
  clang-tidy/utils/DeclRefExprUtils.h
  test/clang-tidy/performance-unnecessary-value-param-delayed.cpp
  test/clang-tidy/performance-unnecessary-value-param.cpp

Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -82,6 +82,7 @@
 struct PositiveConstValueConstructor {
   PositiveConstValueConstructor(const ExpensiveToCopyType ConstCopy) {}
   // CHECK-MESSAGES: [[@LINE-1]]:59: warning: the const qualified parameter 'ConstCopy'
+  // CHECK-FIXES: PositiveConstValueConstructor(const ExpensiveToCopyType& ConstCopy) {}
 };
 
 template  void templateWithNonTemplatizedParameter(const ExpensiveToCopyType S, T V) {
@@ -143,8 +144,29 @@
   Obj.nonConstMethod();
 }
 
-struct NegativeValueCopyConstructor {
-  NegativeValueCopyConstructor(ExpensiveToCopyType Copy) {}
+struct PositiveValueUnusedConstructor {
+  PositiveValueUnusedConstructor(ExpensiveToCopyType Copy) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
+  // CHECK-FIXES: PositiveValueUnusedConstructor(const ExpensiveToCopyType& Copy) {}
+};
+
+struct PositiveValueCopiedConstructor {
+  PositiveValueCopiedConstructor(ExpensiveToCopyType Copy) : Field(Copy) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
+  // CHECK-FIXES: PositiveValueCopiedConstructor(const ExpensiveToCopyType& Copy) : Field(Copy) {}
+  ExpensiveToCopyType Field;
+};
+
+struct PositiveValueMovableConstructor {
+  PositiveValueMovableConstructor(ExpensiveMovableType Copy) : Field(Copy) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:70: warning: parameter 'Copy'
+  // CHECK-FIXES: PositiveValueMovableConstructor(ExpensiveMovableType Copy) : Field(std::move(Copy)) {}
+  ExpensiveMovableType Field;
+};
+
+struct NegativeValueMovedConstructor {
+  NegativeValueMovedConstructor(ExpensiveMovableType Copy) : Field(static_cast(Copy)) {}
+  ExpensiveMovableType Field;
 };
 
 template 
Index: test/clang-tidy/performance-unnecessary-value-param-delayed.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param-delayed.cpp
+++ test/clang-tidy/performance-unnecessary-value-param-delayed.cpp
@@ -64,6 +64,7 @@
 struct PositiveConstValueConstructor {
   PositiveConstValueConstructor(const ExpensiveToCopyType ConstCopy) {}
   // CHECK-MESSAGES: [[@LINE-1]]:59: warning: the const qualified parameter 'ConstCopy'
+  // CHECK-FIXES: PositiveConstValueConstructor(const ExpensiveToCopyType& ConstCopy) {}
 };
 
 template  void templateWithNonTemplatizedParameter(const ExpensiveToCopyType S, T V) {
@@ -125,8 +126,17 @@
   Obj.nonConstMethod();
 }
 
-struct NegativeValueCopyConstructor {
-  NegativeValueCopyConstructor(ExpensiveToCopyType Copy) {}
+struct PositiveValueUnusedConstructor {
+  PositiveValueUnusedConstructor(ExpensiveToCopyType Copy) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
+  // CHECK-FIXES: PositiveValueUnusedConstructor(const ExpensiveToCopyType& Copy) {}
+};
+
+struct PositiveValueCopiedConstructor {
+  PositiveValueCopiedConstructor(ExpensiveToCopyType Copy) : Field(Copy) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
+  // CHECK-FIXES: PositiveValueCopiedConstructor(const ExpensiveToCopyType& Copy) : Field(Copy) {}
+  ExpensiveToCopyType Field;
 };
 
 template 
Index: clang-tidy/utils/DeclRefExprUtils.h
===
--- clang-tidy/utils/DeclRefExprUtils.h
+++ clang-tidy/utils/DeclRefExprUtils.h
@@ -28,23 +28,34 @@
 bool isOnlyUsedAsConst(const VarDecl &Var, const Stmt &Stmt,
ASTContext &Context);
 
-// Returns set of all DeclRefExprs to VarDecl in Stmt.
+/// Returns set of all ``DeclRefExprs`` to ``VarDecl`` within ``Stmt``.
 llvm::SmallPtrSet
 allDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt, ASTContext &Context);
 
-// Returns set of all DeclRefExprs where VarDecl is guaranteed to be accessed in
-// a const fashion.
+/// Returns set of all ``DeclRefExprs`` to ``VarDecl`` within ``Decl``.
+llvm::SmallPtrSet
+allDeclRefExprs(const VarDecl &VarDecl, const Decl &Decl, ASTContext &Context);
+
+/// Returns set of all ``DeclRefExprs`` to ``VarDecl`` within ``Stmt`` where
+/// ``VarDecl`` is guaranteed to be accessed in a const fashion.
 llvm::SmallPtrSet
 constReferenceDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt,
ASTContext &Context);
 
-// Returns true if DeclRefExpr is the argument of a copy-constructor call expr.
-bool isCopyConstructorArgument(const DeclRefExpr &DeclRef, const St

[clang-tools-extra] r290493 - [clang-tidy] Remove local hasInClassInitializer matcher. NFC

2016-12-24 Thread Malcolm Parsons via cfe-commits
Author: malcolm.parsons
Date: Sat Dec 24 08:30:29 2016
New Revision: 290493

URL: http://llvm.org/viewvc/llvm-project?rev=290493&view=rev
Log:
[clang-tidy] Remove local hasInClassInitializer matcher. NFC

Modified:
clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp

Modified: 
clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp?rev=290493&r1=290492&r2=290493&view=diff
==
--- clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp 
(original)
+++ clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp 
Sat Dec 24 08:30:29 2016
@@ -146,10 +146,6 @@ void UseDefaultMemberInitCheck::storeOpt
   Options.store(Opts, "UseAssignment", UseAssignment);
 }
 
-AST_MATCHER(FieldDecl, hasInClassInitializer) {
-  return Node.hasInClassInitializer();
-}
-
 void UseDefaultMemberInitCheck::registerMatchers(MatchFinder *Finder) {
   if (!getLangOpts().CPlusPlus11)
 return;
@@ -167,18 +163,19 @@ void UseDefaultMemberInitCheck::register
   Finder->addMatcher(
   cxxConstructorDecl(
   isDefaultConstructor(), unless(isInstantiated()),
-  forEachConstructorInitializer(allOf(
-  forField(unless(anyOf(isBitField(), hasInClassInitializer(,
-  cxxCtorInitializer(isWritten(),
- withInitializer(ignoringImplicit(Init)))
-  .bind("default",
+  forEachConstructorInitializer(
+  allOf(forField(unless(anyOf(isBitField(),
+  hasInClassInitializer(anything(),
+cxxCtorInitializer(isWritten(),
+   withInitializer(ignoringImplicit(Init)))
+.bind("default",
   this);
 
   Finder->addMatcher(
   cxxConstructorDecl(
   unless(ast_matchers::isTemplateInstantiation()),
   forEachConstructorInitializer(
-  allOf(forField(hasInClassInitializer()),
+  allOf(forField(hasInClassInitializer(anything())),
 cxxCtorInitializer(isWritten(),
withInitializer(ignoringImplicit(Init)))
 .bind("existing",


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


r290495 - Deduplicate several GD.getDecl() calls into Decl * local variable.

2016-12-24 Thread Yaron Keren via cfe-commits
Author: yrnkrn
Date: Sat Dec 24 09:32:39 2016
New Revision: 290495

URL: http://llvm.org/viewvc/llvm-project?rev=290495&view=rev
Log:
Deduplicate several GD.getDecl() calls into Decl * local variable.


Modified:
cfe/trunk/lib/CodeGen/CodeGenModule.cpp

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=290495&r1=290494&r2=290495&view=diff
==
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sat Dec 24 09:32:39 2016
@@ -2300,29 +2300,30 @@ CodeGenModule::GetOrCreateLLVMGlobal(Str
 llvm::Constant *
 CodeGenModule::GetAddrOfGlobal(GlobalDecl GD,
ForDefinition_t IsForDefinition) {
-  if (isa(GD.getDecl()))
-return getAddrOfCXXStructor(cast(GD.getDecl()),
+  const Decl *D = GD.getDecl();
+  if (isa(D))
+return getAddrOfCXXStructor(cast(D),
 getFromCtorType(GD.getCtorType()),
 /*FnInfo=*/nullptr, /*FnType=*/nullptr,
 /*DontDefer=*/false, IsForDefinition);
-  else if (isa(GD.getDecl()))
-return getAddrOfCXXStructor(cast(GD.getDecl()),
+  else if (isa(D))
+return getAddrOfCXXStructor(cast(D),
 getFromDtorType(GD.getDtorType()),
 /*FnInfo=*/nullptr, /*FnType=*/nullptr,
 /*DontDefer=*/false, IsForDefinition);
-  else if (isa(GD.getDecl())) {
+  else if (isa(D)) {
 auto FInfo = &getTypes().arrangeCXXMethodDeclaration(
-cast(GD.getDecl()));
+cast(D));
 auto Ty = getTypes().GetFunctionType(*FInfo);
 return GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/false,
  IsForDefinition);
-  } else if (isa(GD.getDecl())) {
+  } else if (isa(D)) {
 const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD);
 llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
 return GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/false,
  IsForDefinition);
   } else
-return GetAddrOfGlobalVar(cast(GD.getDecl()), /*Ty=*/nullptr,
+return GetAddrOfGlobalVar(cast(D), /*Ty=*/nullptr,
   IsForDefinition);
 }
 


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


[PATCH] D27621: [clang-tidy] check to find declarations declaring more than one name

2016-12-24 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added inline comments.



Comment at: clang-tidy/readability/OneNamePerDeclarationCheck.cpp:22
+
+const internal::VariadicDynCastAllOfMatcher tagDecl;
+

firolino wrote:
> aaron.ballman wrote:
> > We may want to consider adding this to ASTMatchers.h at some point (can be 
> > done in a future patch).
> Is there a `// FIXME: Once I am in AstMatcher.h, remove me.` OK?
You could put in a FIXME, or just create the ASTMatchers patch and mark this 
patch as dependent on that one.



Comment at: clang-tidy/readability/OneNamePerDeclarationCheck.cpp:34
+  // a tag declaration (e.g. struct, class etc.):
+  // class A { } Object1, Object2;  <-- won't be matched
+  Finder->addMatcher(

firolino wrote:
> aaron.ballman wrote:
> > Why do we not want to match this?
> If we decide, whether we transform 
> ```
> class A { 
> } Object1, Object2;
> ``` 
> to
> ```
> class A { 
> } Object1, 
> Object2;
> ``` 
> or
> ```
> class A { 
> } 
> Object1, 
> Object2;
> ``` 
> I might consider adding support for it. Moreover, this kind of definition is 
> usually seen globally and I don't know how to handle globals yet. See 
> http://lists.llvm.org/pipermail/cfe-dev/2015-November/046262.html
I think this should be handled. It can be handled in either of the forms you 
show, or by saying:
```
A Object1;
A Object2;
```
If all of these turn out to be a problem, we can still diagnose without 
providing a fixit.

As for globals in general, they can be handled in a separate patch once we 
figure out the declaration grouping.



Comment at: clang-tidy/readability/OneNamePerDeclarationCheck.cpp:53
+  const LangOptions &LangOpts = getLangOpts();
+  const auto DeclGroup = DeclStatement->getDeclGroup();
+

firolino wrote:
> aaron.ballman wrote:
> > Please don't use `auto` as the type is not spelled out explicitly in the 
> > initialization. Same elsewhere, though it is fine with `diag()` and in for 
> > loop initializers.
> Alright. What about:
> ```
> const auto FirstVarIt = DeclStmt->getDeclGroup().begin();
> const auto DL = SM.getDecomposedLoc(Loc);
> ```
> 
Iterators are fine (because they usually involve a lot of template boilerplate 
for containers and their interfaces are regular and common enough), but the 
call to `getDecomposedLoc()` should not use `auto` -- the reader requires too 
much internal knowledge to understand what the return type is.



Comment at: clang-tidy/readability/OneNamePerDeclarationCheck.cpp:83
+  if (AnyTokenBetweenCommaAndVarName.front() == '#')
+AnyTokenBetweenCommaAndVarName.insert(0, "\n");
+

firolino wrote:
> aaron.ballman wrote:
> > Will this (and the below `\n`) be converted into a CRLF automatically on 
> > platforms where that is the newline character sequence in the source?
> Actually, I was thinking about this but I don't have a Windows etc. with a 
> running llvm environment. Is it OK, if I leave a FIXME for now?
I think it's fine with or without the fixme (it's certainly not the first 
instance of `\n` in the compiler).



Comment at: clang-tidy/readability/OneNamePerDeclarationCheck.cpp:101
+  QualType Type;
+  if (const auto *FirstVar = dyn_cast(*FirstVarIt)) {
+Location = FirstVar->getLocation();

firolino wrote:
> aaron.ballman wrote:
> > You can drop the `const` from the `dyn_cast`, here and elsewhere.
> Alright, but can you explain why?
The `const` on the declaration is sufficient to ensure const correctness. It's 
morally equivalent to:
```
void f(int i) {
  const int ci = i; // No need to const_cast this either.
}
```



Comment at: clang-tidy/readability/OneNamePerDeclarationCheck.cpp:107
+Type = FirstVar->getTypeSourceInfo()->getType();
+while (Type->isLValueReferenceType()) {
+  Type = Type->getPointeeType();

firolino wrote:
> aaron.ballman wrote:
> > Why references and not pointers? Perhaps this needs a comment.
> `// Typedefs on function pointers are covered into LValueReferenceType's` ?
So should this be specific to function pointer types? If so, I don't see that 
predicated anywhere.



Comment at: clang-tidy/readability/OneNamePerDeclarationCheck.cpp:137
+while (Type->isAnyPointerType() || Type->isArrayType())
+  Type = Type->getPointeeOrArrayElementType()->getCanonicalTypeInternal();
+  }

firolino wrote:
> aaron.ballman wrote:
> > Why are you calling the Internal version of this function?
> Because I need its QualType.
You should not call functions that have Internal in the name (generally 
speaking). Those are generally considered to be warts we want to remove once we 
get rid of the last external caller.

All of your uses of `Type` are as a `clang::Type *`, so are you sure you need 
the `QualType` at all? (Btw, you should consider a better name than `Type`.)



Comment at: clang-tidy/readabilit

r290497 - Factor out duplication between partial ordering for class template partial

2016-12-24 Thread Richard Smith via cfe-commits
Author: rsmith
Date: Sat Dec 24 10:40:51 2016
New Revision: 290497

URL: http://llvm.org/viewvc/llvm-project?rev=290497&view=rev
Log:
Factor out duplication between partial ordering for class template partial
specializations and variable template partial specializations.

Modified:
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=290497&r1=290496&r2=290497&view=diff
==
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Sat Dec 24 10:40:51 2016
@@ -2329,19 +2329,37 @@ static Sema::TemplateDeductionResult Con
   return Sema::TDK_Success;
 }
 
-/// Complete template argument deduction for a class template partial
-/// specialization.
-static Sema::TemplateDeductionResult
-FinishTemplateArgumentDeduction(Sema &S,
-ClassTemplatePartialSpecializationDecl 
*Partial,
-const TemplateArgumentList &TemplateArgs,
-  SmallVectorImpl &Deduced,
-TemplateDeductionInfo &Info) {
+DeclContext *getAsDeclContextOrEnclosing(Decl *D) {
+  if (auto *DC = dyn_cast(D))
+return DC;
+  return D->getDeclContext();
+}
+
+template struct IsPartialSpecialization {
+  static constexpr bool value = false;
+};
+template<>
+struct IsPartialSpecialization {
+  static constexpr bool value = true;
+};
+template<>
+struct IsPartialSpecialization {
+  static constexpr bool value = true;
+};
+
+/// Complete template argument deduction for a partial specialization.
+template 
+static typename std::enable_if::value,
+   Sema::TemplateDeductionResult>::type
+FinishTemplateArgumentDeduction(
+Sema &S, T *Partial, const TemplateArgumentList &TemplateArgs,
+SmallVectorImpl &Deduced,
+TemplateDeductionInfo &Info) {
   // Unevaluated SFINAE context.
   EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
   Sema::SFINAETrap Trap(S);
 
-  Sema::ContextRAII SavedContext(S, Partial);
+  Sema::ContextRAII SavedContext(S, getAsDeclContextOrEnclosing(Partial));
 
   // C++ [temp.deduct.type]p2:
   //   [...] or if any template argument remains neither deduced nor
@@ -2363,11 +2381,11 @@ FinishTemplateArgumentDeduction(Sema &S,
   // and are equivalent to the template arguments originally provided
   // to the class template.
   LocalInstantiationScope InstScope(S);
-  ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
-  const ASTTemplateArgumentListInfo *PartialTemplArgInfo
-= Partial->getTemplateArgsAsWritten();
-  const TemplateArgumentLoc *PartialTemplateArgs
-= PartialTemplArgInfo->getTemplateArgs();
+  auto *Template = Partial->getSpecializedTemplate();
+  const ASTTemplateArgumentListInfo *PartialTemplArgInfo =
+  Partial->getTemplateArgsAsWritten();
+  const TemplateArgumentLoc *PartialTemplateArgs =
+  PartialTemplArgInfo->getTemplateArgs();
 
   TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc,
 PartialTemplArgInfo->RAngleLoc);
@@ -2378,21 +2396,19 @@ FinishTemplateArgumentDeduction(Sema &S,
 if (ParamIdx >= Partial->getTemplateParameters()->size())
   ParamIdx = Partial->getTemplateParameters()->size() - 1;
 
-Decl *Param
-  = const_cast(
-  
Partial->getTemplateParameters()->getParam(ParamIdx));
+Decl *Param = const_cast(
+Partial->getTemplateParameters()->getParam(ParamIdx));
 Info.Param = makeTemplateParameter(Param);
 Info.FirstArg = PartialTemplateArgs[ArgIdx].getArgument();
 return Sema::TDK_SubstitutionFailure;
   }
 
   SmallVector ConvertedInstArgs;
-  if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
-  InstArgs, false, ConvertedInstArgs))
+  if (S.CheckTemplateArgumentList(Template, Partial->getLocation(), InstArgs,
+  false, ConvertedInstArgs))
 return Sema::TDK_SubstitutionFailure;
 
-  TemplateParameterList *TemplateParams
-= ClassTemplate->getTemplateParameters();
+  TemplateParameterList *TemplateParams = Template->getTemplateParameters();
   for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
 TemplateArgument InstArg = ConvertedInstArgs.data()[I];
 if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg)) {
@@ -2451,93 +2467,9 @@ Sema::DeduceTemplateArguments(ClassTempl
Deduced, Info);
 }
 
-/// Complete template argument deduction for a variable template partial
-/// specialization.
-/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
-///   May require unifying ClassTemplate(Partial)SpecializationDecl and
-///VarTemplate(Partial)SpecializationDecl wi

[libcxx] r290500 - Fix bug #31387 - not checking end iterator when parsing decimal escape. Thanks to Karen for the report.

2016-12-24 Thread Marshall Clow via cfe-commits
Author: marshall
Date: Sat Dec 24 11:21:03 2016
New Revision: 290500

URL: http://llvm.org/viewvc/llvm-project?rev=290500&view=rev
Log:
Fix bug #31387 - not checking end iterator when parsing decimal escape. Thanks 
to Karen for the report.

Added:
libcxx/trunk/test/std/re/re.regex/re.regex.construct/bad_backref.pass.cpp
Modified:
libcxx/trunk/include/regex

Modified: libcxx/trunk/include/regex
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/regex?rev=290500&r1=290499&r2=290500&view=diff
==
--- libcxx/trunk/include/regex (original)
+++ libcxx/trunk/include/regex Sat Dec 24 11:21:03 2016
@@ -4314,7 +4314,8 @@ basic_regex<_CharT, _Traits>::__parse_de
 else if ('1' <= *__first && *__first <= '9')
 {
 unsigned __v = *__first - '0';
-for (++__first; '0' <= *__first && *__first <= '9'; ++__first)
+for (++__first;
+__first != __last && '0' <= *__first && *__first <= '9'; 
++__first)
 __v = 10 * __v + *__first - '0';
 if (__v > mark_count())
 __throw_regex_error();

Added: libcxx/trunk/test/std/re/re.regex/re.regex.construct/bad_backref.pass.cpp
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/re/re.regex/re.regex.construct/bad_backref.pass.cpp?rev=290500&view=auto
==
--- libcxx/trunk/test/std/re/re.regex/re.regex.construct/bad_backref.pass.cpp 
(added)
+++ libcxx/trunk/test/std/re/re.regex/re.regex.construct/bad_backref.pass.cpp 
Sat Dec 24 11:21:03 2016
@@ -0,0 +1,44 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: libcpp-no-exceptions
+// 
+
+// template > class 
basic_regex;
+
+// template 
+//basic_regex(const basic_string& s);
+
+#include 
+#include 
+#include "test_macros.h"
+
+static bool error_badbackref_thrown(const char *pat)
+{
+bool result = false;
+try {
+std::regex re(pat);
+} catch (const std::regex_error &ex) {
+result = (ex.code() == std::regex_constants::error_backref);
+}
+return result;
+}
+
+int main()
+{
+assert(error_badbackref_thrown("\\1abc"));  // no references
+assert(error_badbackref_thrown("ab(c)\\2def")); // only one reference
+
+//  this should NOT throw, because we only should look at the '1'
+//  See https://llvm.org/bugs/show_bug.cgi?id=31387
+{
+const char *pat1 = "a(b)c\\1234";
+std::regex re(pat1, pat1 + 7); // extra chars after the end.
+}
+}


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


[PATCH] D28081: Make GetStyle return Expected instead of FormatStyle

2016-12-24 Thread Antonio Maiorano via Phabricator via cfe-commits
amaiorano added a comment.

One more thing I forgot to mention is that this change comes from a discussion 
we had on this other change: https://reviews.llvm.org/D27440 where @djasper 
agreed that "fallback-style should only be used when there is no .clang-format 
file. If we find one, and it doesn't parse correctly, we should neither use the 
fallback style nor scan in higher-level directories (not sure whether we 
currently do that).".


https://reviews.llvm.org/D28081



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


[libcxx] r290503 - [libc++] Make __num_get_float hidden

2016-12-24 Thread Shoaib Meenai via cfe-commits
Author: smeenai
Date: Sat Dec 24 12:05:32 2016
New Revision: 290503

URL: http://llvm.org/viewvc/llvm-project?rev=290503&view=rev
Log:
[libc++] Make __num_get_float hidden

It's an internal function and shouldn't be exported. It's also a source
of discrepancy in the published ABI list; these symbols aren't exported
for me on CentOS 7 or Ubuntu 16.04, leading to spurious check-cxx-abilist
failures.

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

Modified:
libcxx/trunk/include/locale
libcxx/trunk/lib/abi/x86_64-unknown-linux-gnu.abilist

Modified: libcxx/trunk/include/locale
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/locale?rev=290503&r1=290502&r2=290503&view=diff
==
--- libcxx/trunk/include/locale (original)
+++ libcxx/trunk/include/locale Sat Dec 24 12:05:32 2016
@@ -779,6 +779,7 @@ long double __do_strtod(con
 }
 
 template 
+_LIBCPP_HIDDEN
 _Tp
 __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
 {

Modified: libcxx/trunk/lib/abi/x86_64-unknown-linux-gnu.abilist
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/lib/abi/x86_64-unknown-linux-gnu.abilist?rev=290503&r1=290502&r2=290503&view=diff
==
--- libcxx/trunk/lib/abi/x86_64-unknown-linux-gnu.abilist (original)
+++ libcxx/trunk/lib/abi/x86_64-unknown-linux-gnu.abilist Sat Dec 24 12:05:32 
2016
@@ -937,9 +937,6 @@
 {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__114error_categoryD1Ev'}
 {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__114error_categoryD2Ev'}
 {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__115__get_classnameEPKcb'}
-{'is_defined': True, 'type': 'FUNC', 'name': 
'_ZNSt3__115__num_get_floatIdEET_PKcS3_Rj'}
-{'is_defined': True, 'type': 'FUNC', 'name': 
'_ZNSt3__115__num_get_floatIeEET_PKcS3_Rj'}
-{'is_defined': True, 'type': 'FUNC', 'name': 
'_ZNSt3__115__num_get_floatIfEET_PKcS3_Rj'}
 {'is_defined': True, 'type': 'FUNC', 'name': 
'_ZNSt3__115__thread_struct25notify_all_at_thread_exitEPNS_18condition_variableEPNS_5mutexE'}
 {'is_defined': True, 'type': 'FUNC', 'name': 
'_ZNSt3__115__thread_struct27__make_ready_at_thread_exitEPNS_17__assoc_sub_stateE'}
 {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__115__thread_structC1Ev'}


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


[PATCH] D27153: [libc++] Make __num_get_float hidden

2016-12-24 Thread Shoaib Meenai via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL290503: [libc++] Make __num_get_float hidden (authored by 
smeenai).

Changed prior to commit:
  https://reviews.llvm.org/D27153?vs=79362&id=82452#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D27153

Files:
  libcxx/trunk/include/locale
  libcxx/trunk/lib/abi/x86_64-unknown-linux-gnu.abilist


Index: libcxx/trunk/lib/abi/x86_64-unknown-linux-gnu.abilist
===
--- libcxx/trunk/lib/abi/x86_64-unknown-linux-gnu.abilist
+++ libcxx/trunk/lib/abi/x86_64-unknown-linux-gnu.abilist
@@ -937,9 +937,6 @@
 {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__114error_categoryD1Ev'}
 {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__114error_categoryD2Ev'}
 {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__115__get_classnameEPKcb'}
-{'is_defined': True, 'type': 'FUNC', 'name': 
'_ZNSt3__115__num_get_floatIdEET_PKcS3_Rj'}
-{'is_defined': True, 'type': 'FUNC', 'name': 
'_ZNSt3__115__num_get_floatIeEET_PKcS3_Rj'}
-{'is_defined': True, 'type': 'FUNC', 'name': 
'_ZNSt3__115__num_get_floatIfEET_PKcS3_Rj'}
 {'is_defined': True, 'type': 'FUNC', 'name': 
'_ZNSt3__115__thread_struct25notify_all_at_thread_exitEPNS_18condition_variableEPNS_5mutexE'}
 {'is_defined': True, 'type': 'FUNC', 'name': 
'_ZNSt3__115__thread_struct27__make_ready_at_thread_exitEPNS_17__assoc_sub_stateE'}
 {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__115__thread_structC1Ev'}
Index: libcxx/trunk/include/locale
===
--- libcxx/trunk/include/locale
+++ libcxx/trunk/include/locale
@@ -779,6 +779,7 @@
 }
 
 template 
+_LIBCPP_HIDDEN
 _Tp
 __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
 {


Index: libcxx/trunk/lib/abi/x86_64-unknown-linux-gnu.abilist
===
--- libcxx/trunk/lib/abi/x86_64-unknown-linux-gnu.abilist
+++ libcxx/trunk/lib/abi/x86_64-unknown-linux-gnu.abilist
@@ -937,9 +937,6 @@
 {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__114error_categoryD1Ev'}
 {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__114error_categoryD2Ev'}
 {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__115__get_classnameEPKcb'}
-{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__115__num_get_floatIdEET_PKcS3_Rj'}
-{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__115__num_get_floatIeEET_PKcS3_Rj'}
-{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__115__num_get_floatIfEET_PKcS3_Rj'}
 {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__115__thread_struct25notify_all_at_thread_exitEPNS_18condition_variableEPNS_5mutexE'}
 {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__115__thread_struct27__make_ready_at_thread_exitEPNS_17__assoc_sub_stateE'}
 {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__115__thread_structC1Ev'}
Index: libcxx/trunk/include/locale
===
--- libcxx/trunk/include/locale
+++ libcxx/trunk/include/locale
@@ -779,6 +779,7 @@
 }
 
 template 
+_LIBCPP_HIDDEN
 _Tp
 __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
 {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r290505 - Fix for PR15623 (corrected r290413 reverted at 290415). The patch eliminates unwanted ProgramState checker data propagation from an operand of the logical operation to operation result.

2016-12-24 Thread Anton Yartsev via cfe-commits
Author: ayartsev
Date: Sat Dec 24 18:57:51 2016
New Revision: 290505

URL: http://llvm.org/viewvc/llvm-project?rev=290505&view=rev
Log:
Fix for PR15623 (corrected r290413 reverted at 290415). The patch eliminates 
unwanted ProgramState checker data propagation from an operand of the logical 
operation to operation result.
The patch also simplifies an assume of a constraint of the form: "(exp 
comparison_op expr) != 0" to true into an assume of "exp comparison_op expr" to 
true. (And similarly, an assume of the form "(exp comparison_op expr) == 0" to 
true as an assume of exp comparison_op expr to false.) which improves precision 
overall.
https://reviews.llvm.org/D22862

Modified:
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
cfe/trunk/test/Analysis/malloc.c
cfe/trunk/test/Analysis/misc-ps.c

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=290505&r1=290504&r2=290505&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Sat Dec 24 18:57:51 2016
@@ -666,23 +666,13 @@ void ExprEngine::VisitLogicalExpr(const
 if (RHSVal.isUndef()) {
   X = RHSVal;
 } else {
-  DefinedOrUnknownSVal DefinedRHS = RHSVal.castAs();
-  ProgramStateRef StTrue, StFalse;
-  std::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS);
-  if (StTrue) {
-if (StFalse) {
-  // We can't constrain the value to 0 or 1.
-  // The best we can do is a cast.
-  X = getSValBuilder().evalCast(RHSVal, B->getType(), RHS->getType());
-} else {
-  // The value is known to be true.
-  X = getSValBuilder().makeIntVal(1, B->getType());
-}
-  } else {
-// The value is known to be false.
-assert(StFalse && "Infeasible path!");
-X = getSValBuilder().makeIntVal(0, B->getType());
-  }
+  // We evaluate "RHSVal != 0" expression which result in 0 if the value is
+  // known to be false, 1 if the value is known to be true and a new symbol
+  // when the assumption is unknown.
+  nonloc::ConcreteInt Zero(getBasicVals().getValue(0, B->getType()));
+  X = evalBinOp(N->getState(), BO_NE, 
+svalBuilder.evalCast(RHSVal, B->getType(), RHS->getType()),
+Zero, B->getType());
 }
   }
   Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), 
X));

Modified: cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp?rev=290505&r1=290504&r2=290505&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp Sat Dec 24 
18:57:51 2016
@@ -254,6 +254,19 @@ ProgramStateRef SimpleConstraintManager:
   assert(BinaryOperator::isComparisonOp(Op) &&
  "Non-comparison ops should be rewritten as comparisons to zero.");
 
+  SymbolRef Sym = LHS;
+
+  // Simplification: translate an assume of a constraint of the form
+  // "(exp comparison_op expr) != 0" to true into an assume of 
+  // "exp comparison_op expr" to true. (And similarly, an assume of the form
+  // "(exp comparison_op expr) == 0" to true into an assume of
+  // "exp comparison_op expr" to false.)
+  if (Int == 0 && (Op == BO_EQ || Op == BO_NE)) {
+if (const BinarySymExpr *SE = dyn_cast(Sym))
+  if (BinaryOperator::isComparisonOp(SE->getOpcode()))
+return assume(State, nonloc::SymbolVal(Sym), (Op == BO_NE ? true : 
false));
+  }
+
   // Get the type used for calculating wraparound.
   BasicValueFactory &BVF = getBasicVals();
   APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType());
@@ -265,7 +278,6 @@ ProgramStateRef SimpleConstraintManager:
   // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which
   // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to
   // the subclasses of SimpleConstraintManager to handle the adjustment.
-  SymbolRef Sym = LHS;
   llvm::APSInt Adjustment = WraparoundType.getZeroValue();
   computeAdjustment(Sym, Adjustment);
 

Modified: cfe/trunk/test/Analysis/malloc.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=290505&r1=290504&r2=290505&view=diff
==
--- cfe/trunk/test/Analysis/malloc.c (original)
+++ cfe/trunk/test/Analysis/malloc.c Sat Dec 24 18:57:51 2016
@@ -1763,6 +1763,17 @@ void testConstEscapeThroughAnotherField(
   constEscape(&(s.x)); // could free s->p!
 } // no-warning
 
+// PR15623
+int testNo

[PATCH] D27680: [CodeGen] Move lifetime.start of a variable when goto jumps back past its declaration

2016-12-24 Thread John McCall via Phabricator via cfe-commits
rjmccall added a comment.

In https://reviews.llvm.org/D27680#630192, @ahatanak wrote:

> Ah, good idea. That sounds like a much simpler and less invasive approach. I 
> agree that the performance impact would probably be small, and if it turns 
> out to have a significant impact, we can reduce the number of times we move 
> the lifetime.start (without moving it retroactively) by checking whether a 
> label was seen.


Oh, good idea, that's a great way to heuristically get the performance back if 
we decide it's important.




Comment at: lib/CodeGen/CGDecl.cpp:917
+  if (!InsertPt)
+Builder.SetInsertPoint(BB, BB->begin());
+  // If InsertPt is a terminator, insert it before InsertPt.

BB->begin() is not necessarily a legal place to insert a call.  This could 
happen if e.g. a scope was unconditionally entered after a statement including 
a ternary expression.

Also, I think lexical scopes don't necessarily have an active basic block upon 
entry, because their entry can be unreachable.  This happens most importantly 
with e.g. switch statements, but can also happen with goto or simply with 
unreachable code (which it's still important to not crash on).


https://reviews.llvm.org/D27680



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


r290509 - [MS ABI] Mangle unnamed enums correctly

2016-12-24 Thread David Majnemer via cfe-commits
Author: majnemer
Date: Sat Dec 24 23:26:02 2016
New Revision: 290509

URL: http://llvm.org/viewvc/llvm-project?rev=290509&view=rev
Log:
[MS ABI] Mangle unnamed enums correctly

Unnamed enums take the name of the first enumerator they define.

Modified:
cfe/trunk/lib/AST/MicrosoftMangle.cpp
cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp

Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=290509&r1=290508&r2=290509&view=diff
==
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Sat Dec 24 23:26:02 2016
@@ -863,21 +863,28 @@ void MicrosoftCXXNameMangler::mangleUnqu
 }
   }
 
-  llvm::SmallString<64> Name(" Name;
   if (DeclaratorDecl *DD =
   Context.getASTContext().getDeclaratorForUnnamedTagDecl(TD)) {
 // Anonymous types without a name for linkage purposes have their
 // declarator mangled in if they have one.
+Name += "getName();
   } else if (TypedefNameDecl *TND =
  Context.getASTContext().getTypedefNameForUnnamedTagDecl(
  TD)) {
 // Anonymous types without a name for linkage purposes have their
 // associate typedef mangled in if they have one.
+Name += "getName();
+  } else if (auto *ED = dyn_cast(TD)) {
+auto EnumeratorI = ED->enumerator_begin();
+assert(EnumeratorI != ED->enumerator_end());
+Name += "getName();
   } else {
 // Otherwise, number the types using a $S prefix.
-Name += "$S";
+Name += "http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp?rev=290509&r1=290508&r2=290509&view=diff
==
--- cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp Sat Dec 24 23:26:02 2016
@@ -343,3 +343,7 @@ A a;
 
 int call_it = (A::default_args(), 1);
 }
+
+enum { enumerator };
+void f(decltype(enumerator)) {}
+// CHECK-DAG: define void @"\01?f@@YAXW4@@@Z"(


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