Coder Social home page Coder Social logo

asutton / clang Goto Github PK

View Code? Open in Web Editor NEW
71.0 22.0 8.0 114.21 MB

License: Other

CMake 0.16% Objective-C 6.63% C++ 70.91% C 18.88% Python 0.82% Objective-C++ 2.04% MATLAB 0.07% Mercury 0.01% LLVM 0.01% Assembly 0.05% Rust 0.01% Cuda 0.27% Mathematica 0.01% Shell 0.01% M 0.01% Fortran 0.01% RenderScript 0.01% Forth 0.01% Perl 0.11% Makefile 0.01%

clang's Introduction

LLVM: 40b1e969f9cb2a0c697e247435193fb006ef1311
libcxx: 64182a5877865cde2538c6038f98e3df33c93a03
libcxxabi: c515867bc14c433febcc574baedd081c078124d1
compiler-rt: 06f1c090cb4e27ea82320bfa7af1e3cfb681edeb

//===----------------------------------------------------------------------===//
// C Language Family Front-end
//===----------------------------------------------------------------------===//

Welcome to Clang.  This is a compiler front-end for the C family of languages
(C, C++, Objective-C, and Objective-C++) which is built as part of the LLVM
compiler infrastructure project.

Unlike many other compiler frontends, Clang is useful for a number of things
beyond just compiling code: we intend for Clang to be host to a number of
different source-level tools.  One example of this is the Clang Static Analyzer.

If you're interested in more (including how to build Clang) it is best to read
the relevant web sites.  Here are some pointers:

Information on Clang:              http://clang.llvm.org/
Building and using Clang:          http://clang.llvm.org/get_started.html
Clang Static Analyzer:             http://clang-analyzer.llvm.org/
Information on the LLVM project:   http://llvm.org/

If you have questions or comments about Clang, a great place to discuss them is
on the Clang development mailing list:
  http://lists.llvm.org/mailman/listinfo/cfe-dev

If you find a bug in Clang, please file it in the LLVM bug tracker:
  http://llvm.org/bugs/

clang's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

clang's Issues

Tuple expansion bug

There appears to be a bug in the instantiation of loop bodies involving the members of a class. From the literal value test:

$class literal_value {
  // Transform members
  constexpr {
    access_kind mode = default_access;
    for... (auto m : $literal_value.members()) { // NOTE: members
      if (mode == default_access) {
        if constexpr (m.is_member_variable()) {
          m.make_private();
        }
        
        if constexpr (m.is_member_function()) {
          m.make_public();
          m.make_constexpr();
        }
        
        if constexpr (m.is_access_specifier())
          mode = m.access();
      }
    }
  } // end metaprogram
}

When the loop is expanded, the conditions appear to be discarded in each block -- they are essentially empty if statements. However, if I change the range variable to e.g., member_functions, the body of the loop is correctly expanded.

It seems like the first expansion of the loop is determining the properties for all subsequent expansions. This could be an artifact of metaclass application.

typename(...) misconstrued as normal 'typename' keyword when used in base list

Low priority problem with the typename(...) syntax:

struct A {};
struct B : A {};

//struct BCopy1 : typename(get<0>($B.bases()).type()) {};
//// ^ "error: 'typename' is redundant; base classes are implicitly types"

using B_base0 = typename(get<0>($B.bases()).type());
struct BCopy2 : B_base0 {};  //Works

The fix I suppose is that wherever Clang is throwing the "typename is redundant" error after a parse, it should now parse just beyond the typename to see if a left parens follows, and only throw the error if it doesn't.

Consider providing e.g. $T::bases_t = decltype($T.bases()), other static member aliases/variables instead of just constexpr fcns

Low priority:
I'm trying to develop some inheritance-handling templates and I find myself constantly writing decltype($T.bases()) when I'd rather write $T::bases or at least $T::bases_t.
I might also slightly prefer $T::size instead $T.size(), seems like the more common way of accessing info when doing template meta programming, for which these reflection properties are very useful.

Segfault with ill-formed tuple-based loops

This causes an ICE:

$class metaclass {
    constexpr {
        for (auto func : $metaclass.member_functions()) {
            // TODO: something interesting here..
        } 
    }
};

The error occurs in EvaluateStatement, which means that the loop is not being properly checked during transformation or substitution (tuples aren't ranges, so we should get a compiler error).

No support for reflecting declaration specifiers

Despite __reflect_specifiers() being a recognized reflection trait intrinsic, attempting to invoke it in C++ code results in the diag::err_reflection_not_supported error message. (To elaborate, in lib/Sema/SemaReflect.cpp, the switch statement in Reflector::Reflect(ReflectionTrait, Decl *) does not handle the URT_ReflectSpecifiers enumeration value, causing control to fall through to the end of the function where the diagnostic is emitted.) This means that there is currently no support for reflecting the specifiers of a declaration.

Incidentally, this was discovered, while building Clang, through the following compiler warning:

[…]/clang/lib/Sema/SemaReflect.cpp:459:11: warning: enumeration value
      'URT_ReflectSpecifiers' not handled in switch [-Wswitch]
  switch (RT) {
          ^

<algorithm> header fails to compile in injection-2 branch

When compiling source containing the header, it fails with following error:

In file included from /usr/lib/gcc/x86_64-linux-gnu/8.0.1/../../../../include/c++/8.0.1/algorithm:62:
In file included from /usr/lib/gcc/x86_64-linux-gnu/8.0.1/../../../../include/c++/8.0.1/bits/stl_algo.h:66:
/usr/lib/gcc/x86_64-linux-gnu/8.0.1/../../../../include/c++/8.0.1/bits/uniform_int_dist.h:176:2: error: expected member name or ';' after declaration specifiers
        __generate(_ForwardIterator __f, _ForwardIterator __t,
        ^
/usr/lib/gcc/x86_64-linux-gnu/8.0.1/../../../../include/c++/8.0.1/bits/uniform_int_dist.h:286:7: error: out-of-line definition of '__generate_impl' does not match any declaration in 'uniform_int_distribution<_IntType>'
      __generate_impl(_ForwardIterator __f, _ForwardIterator __t,
      ^~~~~~~~~~~~~~~

It looks like the header names one of it's functions __generate which is now a special token in the clang branch.

size_t - Ptr must be a pointer to Val type

On object creation, using a size_t variable in a metaclass will hit an assert. Using an int works.

$class test {
	size_t _id = 0;
}

test mtest {};

int main(int, char**) {
	compiler.debug($mtest);
	mtest mt; // <-- Required to hit the assert.
}

Error output :

struct mtest {
unsigned long _id = 0;
}
Assertion failed: (getOperand(0)->getType() == cast(getOperand(1)->getType()
)->getElementType() && "Ptr must be a pointer to Val type!"), function AssertOK, file /Vo
lumes/User/pgroarke/code/llvm/lib/IR/Instructions.cpp, line 1472.
0 clang-5.0 0x0000000103f3ecc8 llvm::sys::PrintStackTrace(llvm::raw_ostre
am&) + 40
1 clang-5.0 0x0000000103f3f376 SignalHandler(int) + 454
2 libsystem_platform.dylib 0x00007fffb54e7b3a _sigtramp + 26
3 libsystem_platform.dylib 0x00007f8a11e59438 _sigtramp + 1553406232
4 libsystem_c.dylib 0x00007fffb536c420 abort + 129
5 libsystem_c.dylib 0x00007fffb5333893 basename_r + 0
6 clang-5.0 0x000000010399e28b llvm::StoreInst::AssertOK() + 203
7 clang-5.0 0x000000010399e328 llvm::StoreInst::StoreInst(llvm::Value*, l
lvm::Value*, bool, llvm::Instruction*) + 24
8 clang-5.0 0x00000001041d5614 llvm::IRBuilder<llvm::ConstantFolder, clan
g::CodeGen::CGBuilderInserter>::CreateStore(llvm::Value*, llvm::Value*, bool) + 68
9 clang-5.0 0x0000000104238777 clang::CodeGen::CodeGenFunction::EmitStore
OfScalar(llvm::Value*, clang::CodeGen::Address, bool, clang::QualType, clang::CodeGen::LV
alueBaseInfo, llvm::MDNode*, bool, clang::QualType, unsigned long long, bool) + 727
10 clang-5.0 0x0000000104227a30 clang::CodeGen::CodeGenFunction::EmitStore
ThroughLValue(clang::CodeGen::RValue, clang::CodeGen::LValue, bool) + 1120
11 clang-5.0 0x000000010420f5ca clang::CodeGen::CodeGenFunction::EmitScala
rInit(clang::Expr const*, clang::ValueDecl const*, clang::CodeGen::LValue, bool) + 554
12 clang-5.0 0x0000000104212367 clang::CodeGen::CodeGenFunction::EmitExprA
sInit(clang::Expr const*, clang::ValueDecl const*, clang::CodeGen::LValue, bool) + 311
13 clang-5.0 0x00000001041db6db clang::CodeGen::CodeGenFunction::EmitIniti
alizerForField(clang::FieldDecl*, clang::CodeGen::LValue, clang::Expr*) + 315
14 clang-5.0 0x00000001041e59d3 EmitMemberInitializer(clang::CodeGen::Code
GenFunction&, clang::CXXRecordDecl const*, clang::CXXCtorInitializer*, clang::CXXConstruc
torDecl const*, clang::CodeGen::FunctionArgList&) + 595
15 clang-5.0 0x00000001041dd056 clang::CodeGen::CodeGenFunction::EmitCtorP
rologue(clang::CXXConstructorDecl const*, clang::CXXCtorType, clang::CodeGen::FunctionArg
List&) + 1910
16 clang-5.0 0x00000001041dc3c5 clang::CodeGen::CodeGenFunction::EmitConst
ructorBody(clang::CodeGen::FunctionArgList&) + 341
17 clang-5.0 0x0000000104368e00 clang::CodeGen::CodeGenFunction::GenerateC
ode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) + 528
18 clang-5.0 0x00000001041b94b0 clang::CodeGen::CodeGenModule::codegenCXXS
tructor(clang::CXXMethodDecl const*, clang::CodeGen::StructorType) + 320
19 clang-5.0 0x00000001043e2c02 (anonymous namespace)::ItaniumCXXABI::emit
CXXStructor(clang::CXXMethodDecl const*, clang::CodeGen::StructorType) + 642
20 clang-5.0 0x00000001043787c4 clang::CodeGen::CodeGenModule::EmitGlobalD
efinition(clang::GlobalDecl, llvm::GlobalValue*) + 452
21 clang-5.0 0x000000010437346b clang::CodeGen::CodeGenModule::EmitDeferre
d() + 235
22 clang-5.0 0x0000000104373493 clang::CodeGen::CodeGenModule::EmitDeferre
d() + 275
23 clang-5.0 0x000000010437297a clang::CodeGen::CodeGenModule::Release() +
42
24 clang-5.0 0x0000000104403724 (anonymous namespace)::CodeGeneratorImpl::
HandleTranslationUnit(clang::ASTContext&) + 100
25 clang-5.0 0x0000000104361157 clang::BackendConsumer::HandleTranslationU
nit(clang::ASTContext&) + 119
26 clang-5.0 0x0000000104cf67d2 clang::ParseAST(clang::Sema&, bool, bool)

  • 466
    27 clang-5.0 0x00000001045b93bc clang::FrontendAction::Execute() + 76
    28 clang-5.0 0x0000000104576841 clang::CompilerInstance::ExecuteAction(cla
    ng::FrontendAction&) + 1201
    29 clang-5.0 0x0000000104612736 clang::ExecuteCompilerInvocation(clang::Co
    mpilerInstance*) + 4934
    30 clang-5.0 0x000000010276e593 cc1_main(llvm::ArrayRef<char const*>, char
    const*, void*) + 1395
    31 clang-5.0 0x000000010276c8a6 main + 10390
    32 libdyld.dylib 0x00007fffb52d8235 start + 1
    33 libdyld.dylib 0x0000000000000037 start + 1255308803
    Stack dump:
  1.  Program arguments: /Volumes/User/pgroarke/code/clang_sutter/usr/bin/clang-5.0 -cc
    

1 -triple x86_64-apple-macosx10.12.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-
isa-usage -emit-obj -mrelax-all -disable-free -main-file-name main.cpp -mrelocation-model
pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -masm-verbose -munwind-tables -t
arget-cpu penryn -target-linker-version 278.4 -dwarf-column-info -debugger-tuning=lldb -r
esource-dir /Volumes/User/pgroarke/code/clang_sutter/usr/lib/clang/5.0.0 -I /Volumes/User
/pgroarke/code/clang_sutter/usr/include/ -stdlib=libc++ -std=c++1z -fdeprecated-macro -fd
ebug-compilation-dir /Volumes/User/pgroarke/code/cppmtl/metaclasses -ferror-limit 19 -fme
ssage-length 89 -stack-protector 1 -fblocks -fobjc-runtime=macosx-10.12.0 -fencode-extend
ed-block-signature -fcxx-exceptions -fexceptions -fmax-type-align=16 -fdiagnostics-show-o
ption -fcolor-diagnostics -freflection -o /var/folders/2v/bwtvk1bx21g31d8sg0j19ddh0000gn/
T/main-b12568.o -x c++ main.cpp

  1.  <eof> parser at end of file
    
  2.  Per-file LLVM IR generation
    
  3.  main.cpp:73:6: Generating code for declaration 'mtest::mtest'
    

clang-5.0: error: unable to execute command: Abort trap: 6
clang-5.0: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 5.0.0
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Volumes/User/pgroarke/code/clang_sutter/usr/bin

Crash on failed lookup

Here's a small example that triggers the crash.

#include <cppx/meta>
#include <cppx/compiler>

using namespace cppx::meta;

struct date {
  int y;
  int m;
  int d;

  virtual void f() { }
};

int main() {
  std::cout << $date::f.is_virtual() << '\n';
}

The problem is that std::cout is not in scope, and the compiler is trying to adjust the "typo". The crash comes from a failed transformation of a template argument.

I strongly suspect that this is because we are not forming the template argument to the constructor to the type of the reflection correctly. It probably needs an actual expression, not just an APInt as the argument.

debug deduced type?

Would it be possible to output what a deduced type looks like?

E.g. for lambda, I'm thinking something like:

auto f = f=4{};
using f_type = std::decay<decltype(f)>::type;

constexpr {
compiler.debug($f_type);
}

Or for templates:

template
void func() {
constexpr {
compiler.debug($T);
}
}

Failed assertion in Sema::CheckMetaclassName()

It looks like Clang does not want us to perform qualified name lookup into transparent contexts (e.g., non-class enumerations and inline namespaces). In Sema::CheckMetaclassName(), we should make sure we find the first enclosing non-transparent context to issue the lookup.

ClangAttrEmitter.cpp build error

Hi,

I've been trying to build your version of clang, but I have several compilation error on the following file:

clang/utils/TableGen/ClangAttrEmitter.cpp

I'm building it along with llvm (clang folder in llvm/tools/) and it is being compiled with gcc 7.2.1

Here is a pastebin with the output https://pastebin.com/zwsssaLC

Access metaclass variables in injections

The following example gives the error :

error: use of non-static data member 't' of 'test' from nested type ''
return t;

$class test {
	int t = 42;
	int get_t() {
		return t;
	}

constexpr {
	-> class {
		int get_meta_test() {
			return t;
		}
	}
} // constexpr
};

test mtest {};

int main(int, char**) {
	compiler.debug($mtest);
	return 0;
}

Under new metaclass format, no way to __generate base classes

I gather you are experimenting with defining metaclasses via a constexpr function, and relying on the user to __generate members via that function. I like it, it's more straightforward to do powerful manipulations, but the problem is there is nowhere to __generate base classes, and so the user-specified bases are being omitted from the outputted class instance.

//Given an "interface" metaclass definition:
template constexpr void interface(T source) { ... }
//...and an interface instance with a base class:
class(interface) Rectangle : public Shape { ... }
//...the following test will fail:
static_assert(std::is_base_of<Shape, Rectangle>::value, "Base class lost in meta-processing!");

Class members don't work

$class my_meta {

};

my_meta MyClass {
public:
    int i;
};

int main() {
    MyClass c;
    c.i = 3;
}

That code fails to compile with the error no member named 'i' in 'MyClass'.
A compiler.debug($MyClass) call shows MyClass as being an empty struct.
The code works fine if the definition of MyClass is changed to class MyClass.

Completely rethink code generation

Token-based code injection does not solve metaprogramming problems. Consider a small class that wants to auto-generate accessors for its members:

struct S2 {
  int a, b, c;

  constexpr {
    for... (auto m : $S2.member_variables())
      -> { int declname("get_" m.name())() const { return m.name(); } }
  }
};

This results in an error claiming m is not found, which is not what we should expect.

As we expand the loop, we should expect to replace (by substitution) the m in the injection with each value of loop variable m in the expansion. This doesn't happen because we haven't done semantic analysis on the declaration in the injection statement. An we really don't want to try to make the substitution lexically because that can dramatically change the meaning of a fragment.

In short, we need to parse injected fragments and actually analyze them.

This is essentially the same as #22, except that it applies to any (potentially) bound identifier within the injection. That is, m in the injection statement should be bound, but isn't.

Reference declarator in for-range-declaration of 'for...' loop causes crash

In the following C++ source code, when the loop variable i is either an lvalue or rvalue reference, Clang will crash due to a failed assertion in VarDecl::checkInitIsICE().

// tuple-for.cpp

#include <iostream>
#include <tuple>

int main() {
  auto t = std::make_tuple(0, 0.1, "meep");

  for... (auto i : t) // This is fine.
    std::cout << i << '\n';

  for... (auto &i : t) // Crash!
    std::cout << i << '\n';

  for... (auto &&i : t) // Crash!
    std::cout << i << '\n';

  return 0;
}

Crash on nested constexpr blocks

This causes the clang to crash:

constexpr {
  constexpr { }
}

For some reason, the innermost lambda isn't being constructed or bound to the declaration correctly.

Injecting members with metaclass names does not work

Consider:

$class foo {
  constexpr {
    -> { void f(foo* p) { } }
  }
};

foo bar { };

The current model injects the tokens void f(foo* p) { } into the token stream and then parses them within the context of the prototype bar. This means the name foo will not be parsed correctly.

We need to parse those tokens as if they were injected into foo and then inject the resulting members into bar.

Incorrect codegen when using variables from a constexpr block in an injected function

I'd expect the following code:

class MyClass {
    constexpr {
        int val = 0;
        -> [val] class { int getFirst() { return val; } }
        ++val;
        -> [val] class { int getSecond() { return val; } }
    }
};

to produce:

int MyClass::getFirst() { return 0; }
int MyClass::getSecond() { return 1; }

However both functions generate the same code: return MyClass::val;.

Move the -freflection flag into the driver

The flag for coroutines is now -fcoroutines-ts (I think). See what changes were made to move the flag out of the front end and into the driver in general. Do the same for the -freflection flag.

Require complete metaclass definitions for class prototypes

Currently, Clang does not prevent nor diagnose this type of recursive declaration, where, within a metaclass definition, a class prototype based on its enclosing metaclass (i.e., a class that is declared using the enclosing metaclass' name as the class-key) is defined.

$class Ifoo {
  Ifoo foo { /* ... */ }; // Should be invalid.
}

To resolve this, a check should be performed (perhaps during semantic analysis) that verifies that the referenced metaclass is not currently being defined.

Are injections supposed to work?

I get "error: expected injection" in examples and simple tests I've used. Are the injections supposed to be working? Other examples (like interfaces) are working fine.

$class the_future_is_now {
	constexpr {
		-> { int metaclasses_are_dope = 0; }
	}
};
// Hopefully the names of the constructs reflect how excited I am about the proposal. Pun intended.

Some changes proposed for discussion

As a base, I propose to consider macros.

Which can be used in the following ways:

  • Function like macro
  • User-defined attribute
  • Definition keyword

Changes for strawman syntax notes:
Replace current:
constexpr void my_metaclass(T target, S source) { ... }
by:
consteval meta::tokenstream my_macro(const meta::tokenstream input) { ... }

Reason for use meta::tokenstream instead meta::type

Separate AST's implementation from the compiler

Also, implement AST's library as part of the std library. Reason for it - separate AST's implementation from the compiler.
So, we have to way to:

  • use the built-in library and convert the stream of tokens to AST's form
  • relying on AST's standardized library to do some optimizations

Note:
Simplest optimization example that comes to mind - we can skip transformation if have implemented AST's library as set of wrappers or if the compiler's internal representation is the same as standardized AST (which is unlikely, but possible).
A similar idea is presented in 1.3.4 Querying changes made on a local copy

Add user possibility choose the implementation with which it is convenient for them to work.

Allow creating a built-in DSL language

Also, it will allow creating a built-in DSL language. For example:

Mathematics based if

http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2018/p0893r1.html

mif( a > b > c) {

} else if( a && b){

} mif( (a + b < a) != c){

}

Backus–Naur form

It can help a project like Boost.Spirit

Also, It will be possible to implement such things as JSX

...

SQL validators

https://github.com/sfackler/rust-postgres-macros

#![feature(plugin)]
#![plugin(postgres_macros)]

fn main() {
    let query = sql!("SELECT * FROM users WHERE name = $1");
    let bad_query = sql!("SELECT * FORM users WEHRE name = $1");
}

Allow abandon preprocessor capabilities

...

Refuse injection or __extend

Violates the principles Be consistent and Be general
Using the AST library we should transfer tokens into AST representation. After we can work with AST like we work with vector or list. If we need to add function, we must first construct it and then put it into the class itself using the member function

Reflection should not be part of the language

https://cplusplus.github.io/reflection-ts/draft.pdf

If we can convert tokens to AST, do we need a special reflection built into the language?
In fact, we are talking about the magic type meta::tokenstream. Which say the compiler pass tokens to the compile-time environment or inject token compile unit.

Homogeneity of compile-time environment

More, more Be general.
Code written once works both in runtime and in compile time.

When we talk about the compile-time environment, we can present this as a separately compiled program instance with a modified entry point to our macro (The implementation is not fundamentally. Of course, at best, expect an interpreter/bytecode machine/JIT).

So, what do I mean by homogeneity? We don't need compiler.error(“message”, m) because we already have print or cout, we also don't need dm.source_location(), we already have meta::tokenstream it is enough to have the starting position like field. Keeping the idea. We must have the same capabilities as in runtime, for example, to be able to open files.

The latter is very important for generators such as go-swagger.

Determinism and portability

There is a significant problem and this should be recognized, therefore some parts of the language cannot be used:

  • code with UB
  • asm inserts

However, for large codebases, this solution can create significant problems. As a solution, the proposed attribute [[meta::allow_unsafe]].
To execute the code in the case of cross-compiling or guarantee its execution using the reference compiler, proposed attribute [[meta::set_environment(str)]] where str is a command that will be executed in the shell (this moment is badly thought out by me, but I think that this is quite important).

P.S. This is not all that I would like to write. I will add some things later.

[metaclass-def] Metaclass declarations are not added to the current declaration context

Metaclass declarations are instead added to the current scope instead of the current declaration context at the end of semantic analysis. As a result, MetaclassDecl nodes are conspicuously missing from the AST.

DeclResult Sema::ActOnMetaclassDefinition(SourceLocation DLoc,
                                          SourceLocation IdLoc,
                                          IdentifierInfo *II, Stmt *Body) {
  assert(isa<CompoundStmt>(Body));
  assert(II);

  // Make sure that this definition doesn't conflict with existing tag
  // definitions.
  //
  // TODO: Should this be valid?
  //
  //    int x;
  //    $class x { }
  //
  // I think that pinning $class x to a tag name means that the variable
  // declaration will effectively hide $class x. We'd have to add $class to
  // the elaborated-type-specifier grammar.
  //
  // This is probably fine for now.
  LookupResult R(*this, II, IdLoc, LookupAnyName, ForRedeclaration);
  LookupName(R, CurScope);
  if (!R.empty()) {
    if (MetaclassDecl *D = R.getAsSingle<MetaclassDecl>()) {
      Diag(IdLoc, diag::err_redefinition) << II;
      Diag(D->getLocation(), diag::note_previous_definition);
    } else {
      Diag(IdLoc, diag::err_redefinition_different_kind) << II;
      if (Decl *D = R.getAsSingle<Decl>())
        Diag(D->getLocation(), diag::note_previous_definition);
    }
    return DeclResult();
  }

  MetaclassDecl *D =
      MetaclassDecl::Create(Context, CurContext, DLoc, IdLoc, II, Body);
  CurScope->AddDecl(D);
  IdResolver.AddDecl(D);

  return D;
}

Metaclasses appear to be completely ignored

In the most recent head (and possibly some earlier ones), even trivial examples fail. It appears that the metaclass definitions are not being applied at all. For example, in the interface example, adding an int to the interface does not generate an error; however, the Circle class that is a subclass of the interface generates the following two errors:

interface.cc:54:22: error: only virtual member functions can be marked 'override'
    int area() const override { return 1; }
                     ^~~~~~~~~
interface.cc:55:34: error: only virtual member functions can be marked 'override'
    void scale_by(double factor) override { }
                                 ^~~~~~~~~
2 errors generated.

It appears as if any metaclass name is treated as equivalent to class. This is compiling with -std=c++1z -Xclang -reflection. It appears that the metaclass definition is being parsed, but is then ignored.

Error when __generating virtual functions in class template metaclass

PREFACE:
I raised issue #51 earlier about the inability to inherit the source classes's base classes into a metaclass defined using the new format (which requires void constexpr function templates).

This is a semantic issue rather than a simple bug, of course: even if we were to allow the constexpr function to be followed by a colon and base list a la the format of a constructor's initializer list, still we would need some special command to generate the list of bases along with their qualifiers -- and how might we handle transforming the base tuple in every conceivable way the user might need?

After considering it, I think the ideal solution (barring significant technical hurdles) would be to use standard class templates, rather than the constexpr function templates or the $class format, to express metaclasses; that way we can handle base specification/transformation using reflection + standard template meta programming tricks, while doing the for... loops as usual in the body of the class template. The need for new semantics would be minimized, making it an easy sell to the standards people.

PROBLEM:
However, the mechanism for __generating a source class's functions within a class template doesn't work right now whenever the source class has a virtual function: we can't __generate such functions; e.g. the example below works as is but uncommenting the "__generate f;" line will cause an error.

EXAMPLE:

template<typename SRC>
struct MyClassTemplateMetaclass  // : public some_inheritance_handler<$SRC.bases(),...>
{
    constexpr {
        for... (auto v : $SRC.variables()) {
            __generate v; //Always works
        }
        for... (auto f : $SRC.functions()) {
            //__generate f; //<--IF YOU UNCOMMENT THIS, YOU GET AN ERROR for any SRC w/virtual fcns
        }
    }
};

struct MySourceWVirtualFcns {
    int myvar;
    virtual void myfcn() {} //If you remove virtual keyword here, no more error on __generate f above.
};

int main() {
    MyClassTemplateMetaclass < MySourceWVirtualFcns > m;
    m.myvar;
    //m.myfcn();
}

To be sure, this problem with virtual functions does not crop up when expressing metaclasses via void constexpr functions; but to repeat issue #51 the problem there is there is no way to inherit the SRC bases:

template<typename SRC>
void constexpr MyConstexprFcnMetaclass_NoWayToInheritBases(SRC source) {
    for... (auto v : source.variables()) {
        __generate v;
    }
    for... (auto f : source.functions()) {
        __generate f; //Works
    }
}

struct ThisBaseWillBeIgnored {
    int missingbasevariable = 2;
};

struct(MyConstexprFcnMetaclass_NoWayToInheritBases) MyMetaclassInstance
    : public ThisBaseWillBeIgnored
{
    int myvar;
    virtual void myfcn() {}
};

int main() {
    MyMetaclassInstance m;
    m.myvar;
    m.myfcn();
    //m.missingbasevariable; //ERROR IF UNCOMMENTED
}

Would be great to get this solved; reflection + the full ability to use __generate/__inject/etc. in the body of class templates is all I think we need for metaclasses, the rest is semantic sugar atop that. (E.g. we wouldn't need "is" and "as"; "is" could be handled through SFINAE trickery, and "as" would be a simple matter of instatiating the metaclass template with the source class (which itself would remain distinct and unchanging).

Thanks for your efforts, please let me know if you would like any help.

Parameters of injected functions

Parameters of injected functions in metaclasses refer to the wrong the declarations when applied. See test/CXX/meta/value.cpp for an example.

It's likely that we're not updating the context correctly when instantiating the new parameters.

Injecting members from within a metaclass fails to parse

For example:

$class movable {
  constexpr {
    bool move = false;
    for... (auto ctor : $movable.constructors()) {
      if (ctor.is_move())
        move = true;
    }
    if (!move) {
      -> { movable(movable&& m) = default; } // error
    }
  }
}

It's likely the case that we haven't established sufficient context to parse the members correctly.

[compiler-error] __compiler_error() cannot be used in inline functions

NOTE: The __compiler_error() intrinsic is implemented in the 'compiler-error' branch.

Currently, the argument to the __compiler_error() intrinsic can be a constant expression of character pointer type. However, when __compiler_error() is invoked within an inline function and the function parameter is passed as the argument, Clang is unable to evaluate the argument at compile-time, even when the enclosing function is called with an apparent string constant.

struct compiler {
  static constexpr void error(const char *message) noexcept {
    __compiler_error(message);
  }
};

int main() {
  compiler::error("Hello, world!"); // error: __compiler_error message is not a string constant
  return 0;
}

GCC's __builtin_constant_p() behaves in a similar manner, suggesting that the problem is inherent in the evaluation of constant expressions and not some random compiler quirk.

constexpr bool is_constant(const char *s) noexcept {
  return __builtin_constant_p(s);
}

int main() {
  constexpr bool x = is_constant("Hello, world!"); // Returns 0 instead of 1.
  return 0;
}

Add a reflection trait to reify types

We need a __reflect_as_type(X) intrinsic that yields the the actual type of the reflected X. And appropriate extensions in the meta library.

template<reflection_t X>
struct type {
  using reflected = __reflect_as_type(X);
};

Generating getter method fails on access

I was using the latest trunk on the compiler explorer. Is this always the current version from git?

I tried to compile the following program:

#include <iostream>

template <typename T>
constexpr void getter(T origin){

    compiler.require(!origin.variables().empty(), "Need to have member variables");

    for...(auto o: origin.variables()){
        if(o.is_public()){
            o.make_private();
            __generate o;

            __generate __fragment struct {
                typename(o) idexpr("get_", o)() const {
                    return idexpr(o);
                }
            };
        }
    }
}

// USER CODE
class(getter) Test {
    public:
        int a;
};

constexpr {compiler.debug($Test);}

int main(){

    Test test;
    test.get_a();

    return 0;
}

This is the generated class:

class Test {

    int a;

public:

    int  get_a() const     {

        return a;

    }

}

But calling test.get_a(); leads to a compiler error:


#0 0x0000557524b49cea llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x1da0cea)

#1 0x0000557524b47b46 llvm::sys::RunSignalHandlers() (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x1d9eb46)

#2 0x0000557524b47c8c SignalHandler(int) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x1d9ec8c)

#3 0x00007fc4b2ce4890 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x12890)

#4 0x000055752664a6af clang::Stmt::getLocStart() const (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x38a16af)

#5 0x0000557526594cd3 clang::Expr::getExprLoc() const (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x37ebcd3)

#6 0x0000557524d1d767 clang::CodeGen::ApplyDebugLocation::ApplyDebugLocation(clang::CodeGen::CodeGenFunction&, clang::Expr const*) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x1f74767)

#7 0x0000557524ec7efa clang::CodeGen::CodeGenFunction::EmitLValue(clang::Expr const*) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x211eefa)

#8 0x0000557524ec87f9 clang::CodeGen::CodeGenFunction::EmitDeclRefLValue(clang::DeclRefExpr const*) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x211f7f9)

#9 0x0000557524ec8226 clang::CodeGen::CodeGenFunction::EmitLValue(clang::Expr const*) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x211f226)

#10 0x0000557524ecc49c clang::CodeGen::CodeGenFunction::EmitCheckedLValue(clang::Expr const*, clang::CodeGen::CodeGenFunction::TypeCheckKind) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x212349c)

#11 0x0000557524efeb59 (anonymous namespace)::ScalarExprEmitter::EmitLoadOfLValue(clang::Expr const*) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x2155b59)

#12 0x0000557524efe272 (anonymous namespace)::ScalarExprEmitter::Visit(clang::Expr*) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x2155272)

#13 0x0000557524f026c8 (anonymous namespace)::ScalarExprEmitter::VisitCastExpr(clang::CastExpr*) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x21596c8)

#14 0x0000557524efdccd (anonymous namespace)::ScalarExprEmitter::Visit(clang::Expr*) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x2154ccd)

#15 0x0000557524efe660 clang::CodeGen::CodeGenFunction::EmitScalarExpr(clang::Expr const*, bool) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x2155660)

#16 0x0000557524d4ab05 clang::CodeGen::CodeGenFunction::EmitReturnStmt(clang::ReturnStmt const&) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x1fa1b05)

#17 0x0000557524d4c8e5 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x1fa38e5)

#18 0x0000557524d4cd9f clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x1fa3d9f)

#19 0x0000557524d7f6c1 clang::CodeGen::CodeGenFunction::EmitFunctionBody(clang::CodeGen::FunctionArgList&, clang::Stmt const*) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x1fd66c1)

#20 0x0000557524d85c5d clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x1fdcc5d)

#21 0x0000557524da0518 clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl, llvm::GlobalValue*) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x1ff7518)

#22 0x0000557524dc4ee0 clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl, llvm::GlobalValue*) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x201bee0)

#23 0x0000557524dc4fc9 clang::CodeGen::CodeGenModule::EmitDeferred() (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x201bfc9)

#24 0x0000557524dc5084 clang::CodeGen::CodeGenModule::Release() (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x201c084)

#25 0x00005575253fa337 (anonymous namespace)::CodeGeneratorImpl::HandleTranslationUnit(clang::ASTContext&) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x2651337)

#26 0x00005575253f8d05 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x264fd05)

#27 0x00005575258bacba clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x2b11cba)

#28 0x00005575253f8107 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x264f107)

#29 0x00005575250c9a16 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x2320a16)

#30 0x00005575250975ec clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x22ee5ec)

#31 0x000055752516db03 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x23c4b03)

#32 0x00005575236dc048 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x933048)

#33 0x00005575236686c6 main (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x8bf6c6)

#34 0x00007fc4b1b9db97 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b97)

#35 0x00005575236d9aba _start (/opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0+0x930aba)

Stack dump:

0.	Program arguments: /opt/compiler-explorer/clang-cppx-trunk-20181027/bin/clang-5.0 -cc1 -triple x86_64-unknown-linux-gnu -S -disable-free -disable-llvm-verifier -discard-value-names -main-file-name example.cpp -mrelocation-model static -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb -coverage-notes-file /tmp/compiler-explorer-compiler118927-10215-1tdhhf0.dm95f/output.gcno -resource-dir /opt/compiler-explorer/clang-cppx-trunk-20181027/lib/clang/5.0.0 -include cppx/meta -include cppx/compiler -I /opt/compiler-explorer/clang-cppx-trunk/include -c-isystem /usr/include/x86_64-linux-gnu -cxx-isystem /usr/include/x86_64-linux-gnu -internal-isystem /opt/compiler-explorer/clang-cppx-trunk-20181027/bin/../include/c++/v1 -internal-isystem /usr/local/include -internal-isystem /opt/compiler-explorer/clang-cppx-trunk-20181027/lib/clang/5.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c++1z -fdeprecated-macro -fdebug-compilation-dir /compiler-explorer -ferror-limit 19 -fmessage-length 0 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -freflection -mllvm --x86-asm-syntax=intel -o /tmp/compiler-explorer-compiler118927-10215-1tdhhf0.dm95f/output.s -x c++ <source> 

1.	<eof> parser at end of file

2.	Per-file LLVM IR generation

3.	Generating code for declaration 'Test::get_a'

clang-5.0: error: unable to execute command: Segmentation fault (core dumped)

clang-5.0: error: clang frontend command failed due to signal (use -v to see invocation)

clang version 5.0.0 (https://github.com/asutton/clang.git dbca1f802cd36d5f7116b24487da29d1c64c3a0e) (https://github.com/llvm-mirror/llvm.git 40b1e969f9cb2a0c697e247435193fb006ef1311)

Target: x86_64-unknown-linux-gnu

Thread model: posix

InstalledDir: /opt/compiler-explorer/clang-cppx-trunk/bin

clang-5.0: note: diagnostic msg: PLEASE submit a bug report to http://llvm.org/bugs/ and include the crash backtrace, preprocessed source, and associated run script.

clang-5.0: note: diagnostic msg: 

********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:

Preprocessed source(s) and associated run script(s) are located at:

clang-5.0: note: diagnostic msg: /tmp/example-13e4ff.cpp

clang-5.0: note: diagnostic msg: /tmp/example-13e4ff.sh

clang-5.0: note: diagnostic msg: 

********************

Compiler returned: 254

Segfault on unfound meta-class references

The following causes a segfault:

$class meta {
    constexpr {
        for... (auto func : $not_meta.member_functions()) {} 
    }
};

It gives the error:

error: reflection of an overloaded name
        for... (auto func : $not_meta.member_functions()) {} 
                             ^
<source>:6:30: error: use of undeclared identifier 'not_meta'

Possibly crash has same root cause as #16, given similarity (to me anyway!)

Allow variables and functions to have dependent idexpr names.

For example:

$class foo {
  int idexpr($foo.name() "_bar") = 0;
}

This is currently rejected because variables must have identifiers as names.

This raises an interesting question... how do we resolve references to these things? This is not an identifier, normal lookup mechanisms won't quite work. Leave them unresolved?

Injection of namespace-scoped members cause linker errors

For example, this program:

constexpr {
  -> { void foo() { }; }
}

int main() {
  foo() { }
}

results in an undefined reference for foo. In looking at the IR, the definition is not emitted even though the declaration in the AST is marked as used.

Injected statements are not added to compound-statement bodies

Which causes assertions in codegen. For example:

int main() {
  constexpr { -> { int n = 0; } }
  ++n; // crash!
}

We need to return injected statements back to the point at which a compound-statement parses the declaration-statement containing the constexpr declaration.

Metaclass member injection breaks semantic analysis

The invocation of Sema::InjectMetaclassMembers() in Sema::ActOnFields() appears to break semantic analysis of metaclass members that are injected into the definition of a class prototype.

In the following example, two member functions in the metaclass IPoint reference member variables whose declarations appear later in the metaclass' definition. Ordinarily (that is, within the definition of a regular class), this would be perfectly valid C++.

The current iteration of Clang disagrees.

// simple-metaclass.cpp

$class IPoint {
  double getX() const { return x; }
  double getY() const { return y; }

  double x;
  double y;
}

IPoint Point {
  // ...
};

int main() {
  Point p1;
  // Do other stuff...
  return 0;
}
$ clang++ -std=c++11 -Xclang -freflection -o simple-metaclass simple-metaclass.cpp
simple-metaclass.cpp:4:32: error: 'x' is not a member of class 'const Point'
  double getX() const { return x; }
                               ^
simple-metaclass.cpp:5:32: error: 'y' is not a member of class 'const Point'
  double getY() const { return y; }
                               ^
2 errors generated.

EDIT: The same error occurs even when the member variables precede the member functions. 🤦‍♀️

// simple-metaclass.cpp

$class IPoint {
  double x;
  double y;

  double getX() const { return x; }
  double getY() const { return y; }
}

IPoint Point {
  // ...
};

int main() {
  Point p1;
  // Do other stuff...
  return 0;
}
$ clang++ -std=c++11 -Xclang -freflection -o simple-metaclass simple-metaclass.cpp 
simple-metaclass.cpp:7:32: error: 'x' is not a member of class 'const Point'
  double getX() const { return x; }
                               ^
simple-metaclass.cpp:8:32: error: 'y' is not a member of class 'const Point'
  double getY() const { return y; }
                               ^
2 errors generated.

Unable to compile constexpr declarations when not in C++17 mode

Any instance of a constexpr declaration will result in a fatal error when compiling without either the -std=c++14 or -std=c++1z option, due to various requirements regarding constexpr functions' return and parameter types.

Since constexpr declarations are represented internally as constexpr functions returning void (within function contexts, they're represented as lambda call operators), they will inevitably fail semantic checks that enforce the requirement that constexpr functions have literal return and parameter types. Enabling the -std=c++1z option will silence all of these errors. (Note: void and closure types are redefined as literal types in C++14 and C++17, respectively.)

// constexpr-decl.cpp

class foo {
  constexpr {
    // Will compile with -std=c++14.
  }
};

int main() {
  constexpr {
    // Will compile with -std=c++1z.
  }
  return 0;
}
$ clang++ -std=c++11 -o constexpr-decl constexpr-decl.cpp
constexpr-decl.cpp:4:3: error: constexpr function's return type 'void' is not a literal type
  constexpr {
  ^
constexpr-decl.cpp:4:3: error: expression is not an integral constant expression
  constexpr {
  ^~~~~~~~~~~
note: non-literal type 'void' cannot be used in a constant expression
constexpr-decl.cpp:10:3: error: constexpr function's return type 'void' is not a literal type
  constexpr {
  ^
constexpr-decl.cpp:10:3: error: expression is not an integral constant expression
  constexpr {
  ^~~~~~~~~~~
constexpr-decl.cpp:10:3: note: non-literal type 'void' cannot be used in a constant expression
4 errors generated.
$ clang++ -std=c++14 -o constexpr-decl constexpr-decl.cpp
constexpr-decl.cpp:10:3: error: expression is not an integral constant expression
  constexpr {
  ^~~~~~~~~~~
constexpr-decl.cpp:10:3: note: non-literal type '(lambda at constexpr-decl.cpp:10:3)' cannot be used
      in a constant expression
1 error generated.

Segfault/error calling `is_public` on member functions

(NB I'm am not up-to-date with the latest syntax, so excuse any mixing of old and new syntax here)

The code:

#include <cppx/compiler>
#include <cppx/meta>

using namespace cppx::meta;

$class interface {
    virtual ~interface();
    constexpr {
        for... (auto func : $interface.member_functions()) {
            if (!func.is_public()) {
                compiler.error("interfaces must be public");
            }
        } 
    }
};

interface Foo {
    /*public:*/
    void monkey();
};

With the public: commented out, yields a stack of error messages seemingly internal to the <meta> header:

In file included from <source>:2:
/opt/compiler-explorer/cppx/clang-cppx-0.1.0/include/cppx/meta:28:12: error: no viable conversion from returned value of type 'unsigned int' to function return type 'cppx::meta::v1::decl_traits'
    return __reflect_traits(X);
           ^~~~~~~~~~~~~~~~
/opt/compiler-explorer/cppx/clang-cppx-0.1.0/include/cppx/meta:63:21: note: in instantiation of member function 'cppx::meta::v1::decl<93855273>::traits' requested here
    return decl<X>::traits.access;
                    ^
/opt/compiler-explorer/cppx/clang-cppx-0.1.0/include/cppx/meta:69:12: note: in instantiation of member function 'cppx::meta::v1::named<93855273>::access' requested here
    return access() == public_access;
           ^
<source>:10:22: note: in instantiation of member function 'cppx::meta::v1::named<93855273>::is_public' requested here
            if (!func.is_public()) {
                      ^
<source>:9:60: note: in instantiation of loop body expansion
        for... (auto func : $interface.member_functions()) {
                                                           ^
/opt/compiler-explorer/cppx/clang-cppx-0.1.0/include/cppx/traits.hpp:58:8: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'unsigned int' to 'const cppx::meta::v1::decl_traits &' for 1st argument
struct decl_traits {
       ^
/opt/compiler-explorer/cppx/clang-cppx-0.1.0/include/cppx/traits.hpp:58:8: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'unsigned int' to 'cppx::meta::v1::decl_traits &&' for 1st argument
In file included from <source>:2:
/opt/compiler-explorer/cppx/clang-cppx-0.1.0/include/cppx/meta:63:12: error: base of member reference is a function; perhaps you meant to call it with no arguments?
    return decl<X>::traits.access;
           ^~~~~~~~~~~~~~~
                          ()
/opt/compiler-explorer/cppx/clang-cppx-0.1.0/include/cppx/meta:69:12: note: in instantiation of member function 'cppx::meta::v1::named<93855273>::access' requested here
    return access() == public_access;
           ^
<source>:10:22: note: in instantiation of member function 'cppx::meta::v1::named<93855273>::is_public' requested here
            if (func.is_public()) {
                     ^
<source>:9:60: note: in instantiation of loop body expansion
        for... (auto func : $interface.member_functions()) {
                                                           ^

With the public: commented in, the compiler segfaults:

Stack dump:
0.	Program arguments: /opt/compiler-explorer/cppx/clang-cppx-0.1.0/bin/clang-5.0 -cc1 -triple x86_64-unknown-linux-gnu -S -disable-free -disable-llvm-verifier -discard-value-names -main-file-name example.cpp -mrelocation-model static -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -momit-leaf-frame-pointer -dwarf-column-info -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb -coverage-notes-file /tmp/compiler-explorer-compiler117323-11-cvtowa.jjbkv5cdi/output.gcno -resource-dir /opt/compiler-explorer/cppx/clang-cppx-0.1.0/bin/../lib/clang/5.0.0 -I /opt/compiler-explorer/cppx/clang-cppx-0.1.0/include -c-isystem /usr/include/x86_64-linux-gnu -cxx-isystem /usr/include/x86_64-linux-gnu -internal-isystem /opt/compiler-explorer/cppx/clang-cppx-0.1.0/bin/../include/c++/v1 -internal-isystem /usr/local/include -internal-isystem /opt/compiler-explorer/cppx/clang-cppx-0.1.0/bin/../lib/clang/5.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O1 -std=c++1z -fdeprecated-macro -fdebug-compilation-dir /compiler-explorer -ferror-limit 19 -fmessage-length 0 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -freflection -mllvm --x86-asm-syntax=intel -o /tmp/compiler-explorer-compiler117323-11-cvtowa.jjbkv5cdi/output.s -x c++ <source> 
1.	<source>:20:2: current parser token ';'
2.	<source>:17:1: parsing struct/union/class body 'Foo'
3.	/opt/compiler-explorer/cppx/clang-cppx-0.1.0/bin/../include/c++/v1/__tuple:25:50: instantiating class definition 'std::__1::tuple_size<cppx::meta::v1::filtered_tuple<cppx::meta::v1::scope<113944914>::member_info, is_member_function> >'
4.	/opt/compiler-explorer/cppx/clang-cppx-0.1.0/include/cppx/tuple.hpp:116:32: instantiating function definition 'cppx::meta::v1::filtered_tuple<cppx::meta::v1::scope<113944914>::member_info, is_member_function>::size'
5.	/opt/compiler-explorer/cppx/clang-cppx-0.1.0/include/cppx/tuple.hpp:102:1: instantiating function definition 'cppx::meta::v1::tuple_count_type_if<is_member_function, cppx::meta::v1::reflected_tuple<cppx::meta::v1::scope<113944914>::member_info> >'
6.	/opt/compiler-explorer/cppx/clang-cppx-0.1.0/include/cppx/tuple.hpp:74:1: instantiating function definition 'cppx::meta::v1::tuple_for_each<cppx::meta::v1::reflected_tuple<cppx::meta::v1::scope<113944914>::member_info>, cppx::meta::v1::detail::count_type_if_fn<is_member_function> >'
7.	/opt/compiler-explorer/cppx/clang-cppx-0.1.0/include/cppx/tuple.hpp:64:1: instantiating function definition 'cppx::meta::v1::detail::tuple_for_each_recursive<0, cppx::meta::v1::reflected_tuple<cppx::meta::v1::scope<113944914>::member_info>, cppx::meta::v1::detail::count_type_if_fn<is_member_function> >'
8.	/opt/compiler-explorer/cppx/clang-cppx-0.1.0/include/cppx/tuple.hpp:64:1: instantiating function definition 'cppx::meta::v1::detail::tuple_for_each_recursive<1, cppx::meta::v1::reflected_tuple<cppx::meta::v1::scope<113944914>::member_info>, cppx::meta::v1::detail::count_type_if_fn<is_member_function> >'
9.	/opt/compiler-explorer/cppx/clang-cppx-0.1.0/include/cppx/meta:102:27: instantiating function definition 'cppx::meta::v1::scope<113944914>::member_info::get<1>'
clang-5.0: error: unable to execute command: Segmentation fault (core dumped)

Build is from 0a1eb43

Make injection capture implicit

Don't allow a list of expressions in the capture list. Just scan the enclosing scope for local declarations and capture those.

In cppx/meta/tuple.hpp, change T::size() to std::tuple_size<T>::value

Small issue, simple fix: in the tuple.hpp file in your reflection library, you have specified std::tuple_size<...> specializations in an apparent effort to generalize your tuple algorithms so they can be used on e.g. std::tuples in addition to your reflected_tuples or whatever; however in the two tuple_for_each_recursive definitions, T::size() is still used in the enable_if_t<...> instead of std::tuple_size<T>::value, making it not as general as it could be -- it fails with std::tuples right now.

Parse multiple decls/stmts inside of injections

Support this:

constexpr {
  -> {
    void f() { }
    void g() { }
  }
}

I believe the parser will currently lex all contained declarations and statements, but we need to ensure that they are processed as multiple declarations or statements.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.