[PATCH] D61790: [C++20] add consteval specifier

2019-05-14 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added a comment.

Thanks for working on this!

Comments on the general approach:

- We should only evaluate each immediate invocation once (this will become 
essential once we start supporting reflection -- and particularly operations 
that mutate the AST -- inside `consteval` functions).
- Each time an immediate invocation is formed, you should create a 
`ConstantExpr` AST node wrapping that call to reflect that it is a constant.
- You should change `ConstantExpr` to store an `APValue` representing the 
evaluated value of the expression.

Most of the above should be done as a separate preparatory change; we should be 
able to remove a lot of the existing ad-hoc caching of evaluated values (eg, 
for enumerators and the initializers of variables) at the same time.

Please also split this into smaller pieces. If you split off a patch to just 
add the keyword, parsing, and AST representation for the `consteval` specifier 
(but treat it identically to `constexpr` for constant evaluation purposes), 
that'd be a good first patch for this feature.




Comment at: clang/include/clang/AST/Decl.h:2102
   /// Whether this is a (C++11) constexpr function or constexpr constructor.
   bool isConstexpr() const { return FunctionDeclBits.IsConstexpr; }
   void setConstexpr(bool IC) { FunctionDeclBits.IsConstexpr = IC; }

Please rename this to `isConstexprSpecified()` (compare this to how we model 
`inline`, which has similar behavior: it can be explicit, or can be implied by 
other properties of the function).



Comment at: clang/include/clang/AST/Decl.h:2109
+
+  bool isConstexprOrConsteval() const { return isConstexpr() || isConsteval(); 
}
+

Both the `constexpr` and `consteval` specifiers make a function a "constexpr 
function", so I think this should be called simply `isConstexpr`; callers that 
want to distinguish `constexpr` from `consteval` can use `isConsteval()` (or we 
can add a `getConstexprKind()` or similar function).



Comment at: clang/include/clang/AST/DeclCXX.h:2115
+QualType T, TypeSourceInfo *TInfo, StorageClass SC,
+bool isInline, bool isConstexpr, bool isConsteval,
+SourceLocation EndLocation)

Instead of the three bool flags in a row here (which will make call sites hard 
to read), consider using an enum, perhaps:

```
enum class ConstexprSpecifierKind { None, Constexpr, Consteval };
```



Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:2297-2300
+def err_consteval_cannot_be_constant_eval : Error<
+  "call to %0 cannot be constant evaluated">;
+def note_argument_n_cannot_be_constant_eval : Note<
+  "argument %0 cannot be constant evaluated">;

It would be useful in these diagnostics to explain why the call is required to 
be constant evaluated; please also use the standard terminology "constant 
expression" here. (Eg, "call to consteval function %0 is not a constant 
expression")



Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:2308-2314
 def err_constexpr_tag : Error<
   "%select{class|struct|interface|union|enum}0 cannot be marked constexpr">;
-def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">;
+def err_constexpr_dtor : Error<"destructor cannot be marked %0">;
+def err_invalid_consteval_decl_kind : Error<
+  "operator %select{new|delete|new[]|delete[]}0 cannot be marked consteval">;
+def err_take_adress_of_consteval_decl : Error<
+  "taking address of a %0">;

In these diagnostics (including the existing one for tags), we should say 
"declared constexpr" not "marked constexpr".



Comment at: clang/include/clang/Basic/TokenKinds.def:390-391
 
+// C++ consteval proposal
+CXX2A_KEYWORD(consteval , 0)
+

This and `char8_t` are both adopted C++2a features now (they'e not just 
proposals any more); please change the comment to just "C++2a keywords".



Comment at: clang/include/clang/Sema/DeclSpec.h:404
   SourceLocation FS_forceinlineLoc;
-  SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc;
+  SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc, ConstevalLoc;
   SourceLocation TQ_pipeLoc;

I think it would be preferable to track only one location here (for the 
`constexpr` / `consteval` specifier) and store a constexpr specifier kind 
instead of `Constexpr_specified`, like we do for the other kinds of specifier 
for which we allow only one of a set of keywords.



Comment at: clang/include/clang/Sema/Sema.h:985-986
+///   cases in a switch statement).
+/// - "immediate function context" in C++2a terms, a call to a function
+///   marked as consteval
 ConstantEvaluated,

An "immediate function context" is also "potentially evaluated"; I think what 
we want to say here is something like "The current 

[PATCH] D61790: [C++20] add consteval specifier

2019-05-14 Thread Eli Friedman via Phabricator via cfe-commits
efriedma added a comment.

"complex" in this context is the C99 `_Complex`, which is supported in C++ as 
an extension, using the same syntax as C. You can just declare a variable with 
type `_Complex float`.  If you need to manipulate the real and imaginary parts 
of a variable, you can use the gcc extension `__real__`/`__imag__`, although I 
don't think you need to.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61790/new/

https://reviews.llvm.org/D61790



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


[PATCH] D61790: [C++20] add consteval specifier

2019-05-13 Thread Gabor Marton via Phabricator via cfe-commits
martong resigned from this revision.
martong added a comment.
Herald added a subscriber: rnkovacs.

ASTImporter.cpp looks good to me.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61790/new/

https://reviews.llvm.org/D61790



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


[PATCH] D61790: [C++20] add consteval specifier

2019-05-10 Thread Tyker via Phabricator via cfe-commits
Tyker created this revision.
Tyker added a reviewer: rsmith.
Herald added a reviewer: martong.
Herald added a reviewer: shafik.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

this revision adds the consteval specifier as specified by 
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1073r3.html

Changes:

- add the consteval keyword.
- add parsing of consteval specifier for normal declarations and lambdas 
expressions.
- add the a bit to FunctionDeclBits for consteval.
- adapt creation of FunctionDecl and some classes inheriting from it to take an 
extra bool for consteval.
- change most calls to FunctionDecl::isConstexpr into call to 
FunctionDecl::isConstexprOrConsteval.
- add semantic checking to prevent call to consteval function that cannot be 
constant evaluated.
- add semantic checking to prevent taking address from consteval function.
- add semantic checking to prevent consteval specified allocation function.
- add tests for semantic.

The code-gen has not yet been adapted, but it will need to be change to not 
emit consteval function and ensure calls to consteval function are folded 
correctly.


Repository:
  rC Clang

https://reviews.llvm.org/D61790

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/AST/DeclBase.h
  clang/include/clang/AST/DeclCXX.h
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Sema/DeclSpec.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ASTImporter.cpp
  clang/lib/AST/Decl.cpp
  clang/lib/AST/DeclCXX.cpp
  clang/lib/AST/DeclPrinter.cpp
  clang/lib/AST/ExprConstant.cpp
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/Analysis/ReachableCode.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseExprCXX.cpp
  clang/lib/Parse/ParseTentative.cpp
  clang/lib/Sema/DeclSpec.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaCoroutine.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaLambda.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/lib/Sema/TreeTransform.h
  clang/lib/Serialization/ASTReaderDecl.cpp
  clang/lib/Serialization/ASTWriterDecl.cpp
  clang/test/SemaCXX/cxx2a-compat.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp

Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -0,0 +1,224 @@
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only %s -verify
+
+int i_global; // expected-note+ {{declared here}}
+extern int i_extern; // expected-note+ {{declared here}}
+const int i_const = 0;
+constexpr int i_constexpr = 0;
+
+consteval int f_eval(int i) {
+// expected-note@-1+ {{consteval function declared here}}
+  return i;
+}
+
+constexpr auto l_eval = [](int i) consteval {
+// expected-note@-1+ {{consteval operator declared here}}
+  return i;
+};
+
+constexpr int f_expr(int i) {
+  return i;
+}
+
+struct A {
+  consteval int f_eval(int i) const {
+// expected-note@-1+ {{consteval function declared here}}
+return i;
+  }
+};
+
+constexpr A a;
+
+namespace invalid_call_args {
+
+int d0 = f_eval(0);
+int l0 = l_eval(0);
+int m0 = a.f_eval(0);
+int d2 = f_eval(i_extern);
+// expected-error@-1 {{call to consteval function cannot be constant evaluated}}
+// expected-note@-2 {{argument 0 cannot be constant evaluated}}
+// expected-note@-3 {{not allowed in a constant expression}}
+int l2 = l_eval(i_extern);
+// expected-error@-1 {{call to consteval operator cannot be constant evaluated}}
+// expected-note@-2 {{argument 0 cannot be constant evaluated}}
+// expected-note@-3 {{not allowed in a constant expression}}
+int m2 = a.f_eval(i_extern);
+// expected-error@-1 {{call to consteval function cannot be constant evaluated}}
+// expected-note@-2 {{argument 0 cannot be constant evaluated}}
+// expected-note@-3 {{not allowed in a constant expression}}
+int d4 = f_eval(i_const);
+int l4 = l_eval(i_const);
+int m4 = a.f_eval(i_const);
+int d6 = f_eval(i_constexpr);
+int l6 = l_eval(i_constexpr);
+int m6 = a.f_eval(i_constexpr);
+int d8 = f_eval(i_global);
+// expected-error@-1 {{call to consteval function cannot be constant evaluated}}
+// expected-note@-2 {{argument 0 cannot be constant evaluated}}
+// expected-note@-3 {{not allowed in a constant expression}}
+int l8 = l_eval(i_global);
+// expected-error@-1 {{call to consteval operator cannot be constant evaluated}}
+// expected-note@-2 {{argument 0 cannot be constant evaluated}}
+// expected-note@-3 {{not allowed in a constant expression}}
+int m8 = a.f_eval(i_global);
+// expected-error@-1 {{call to consteval function cannot be constant evaluated}}
+// expected-note@-2 {{argument 0 cannot be constant evaluated}}
+// expected-note@-3 {{not allowed in a constant expression}}
+