I am drafting some modification on a C++ I have been given. In order to separate my contributions for the time being, I would like to extend the class definition in a original header file by including another file.
In terms of pseudo code it would be something like this
class OldClass : public OldSuperClass
{
private:
blah blah
protected:
blah blah
public:
blah blah
#include "NewStuff.h" // this is the action
blah blah
};
This was inspired by the explanation that
the #include directive causes the preprocessor to include another file, usually a header file" (C++ Pocket Reference, O'Reilly).
The file NewStuff contains vanilla definitions like
#ifndef _JNew_
#define _JNew_
#include <iomanip> // this is the mistake (see comments and answers)
const int apha = 1;
double beta;
blah blah
inline double HalfDif (double a, double b)
{
return (a - b) * 0.5;
}
#endif
I would want these to become public members of OldClass. At compile time, however, I receive errors of the type
error: expected unqualified-id at end of input
error: expected unqualified-id before ‘namespace’
Searching across the internet fora, these seem to indicate that there is a syntax problem with braces and semicolons.
However, in this case the error is triggered by the inclusion, and I am not familiar with the rules that I have apparently infringed.
What is wrong with the action above, and how can it be made to work? As a temporary hack would actually be quite handy.
What you have done can work. Just consider that #includes are simply about textual replacement. What you can put in the header is for example:
// xy.h
int x;
So when it is expanded in:
struct foo {
#include "xy.h"
};
The result becomes
struct foo {
// xy.h
int x;
};
Your code is invalid after replacing the #include with the contents of the header.
However, even if you fix that, this is uncommon and will make a good surprise for many reading the code (real life: surprises yeah, coding: surprises meh). Headers are not made to be used like this. At least use a different extension like .incl. But even then it is not a "nice" solution. It will result in a mess pretty fast once you have to apply modifications in different places in the code. If you want to keep your modifications apart from the rest of the code you should use a version control system where you can create your working branch without disturbing others working on other branches.
Related
I keep reading that it's bad to do so, but I don't feel those answers fully answer my specific question.
It seems like it could be really useful in some cases. I want to do something like the following:
class Example {
private:
int val;
public:
void my_function() {
#if defined (__AVX2__)
#include <function_internal_code_using_avx2.h>
#else
#include <function_internal_code_without_avx2.h>
#endif
}
};
If using #include in the middle of code is bad in this example, what would be a good practice approach for to achieve what I'm trying to do? That is, I'm trying to differentiate a member function implementation in cases where avx2 is and isn't available to be compiled.
No it is not intrinsically bad. #include was meant to allow include anywhere. It's just that it's uncommon to use it like this, and this goes against the principle of least astonishment.
The good practices that were developed around includes are all based on the assumption of an inclusion at the start of a compilation unit and in principle outside any namespace.
This is certainly why the C++ core guidelines recommend not to do it, being understood that they have normal reusable headers in mind:
SF.4: Include .h files before other declarations in a file
Reason
Minimize context dependencies and increase readability.
Additional remarks: How to solve your underlying problem
Not sure about the full context. But first of all, I wouldn't put the function body in the class definition. This would better encapsulate the implementation specific details for the class consumers, which should not need to know.
Then you could use conditional compilation in the body, or much better opt for some policy based design, using templates to configure the classes to be used at compile time.
I agree with what #Christophe said. In your case I would write the following code
Write a header commonInterface.h
#pragma once
#if defined (__AVX2__)
void commonInterface (...) {
#include <function_internal_code_using_avx2.h>
}
#else
void commonInterface (...) {
#include <function_internal_code_without_avx2.h>
}
#endif
so you hide the #if defined in the header and still have good readable code in the implementation file.
#include <commonInterface>
class Example {
private:
int val;
public:
void my_function() {
commonInterface(...);
}
};
#ifdef __AVX2__
# include <my_function_avx2.h>
#else
# include <my_function.h>
#endif
class Example {
int val;
public:
void my_function() {
# ifdef __AVX2__
my_function_avx2(this);
# else
my_function(this);
# endif
}
};
Whether it is good or bad really depends on the context.
The technique is often used if you have to write a great amount of boilerplate code. For example, the clang compiler uses it all over the place to match/make use of all possible types, identifiers, tokens, and so on. Here is an example, and here another one.
If you want to define a function differently depending on certain compile-time known parameters, it's seen cleaner to put the definitions where they belong to be.
You should not split up a definition of foo into two seperate files and choose the right one at compile time, as it increases the overhead for the programmer (which is often not just you) to understand your code.
Consider the following snippet which is, at least in my opinion, much more expressive:
// platform.hpp
constexpr static bool use_avx2 = #if defined (__AVX2__)
true;
#else
false;
#endif
// example.hpp
class Example {
private:
int val;
public:
void my_function() {
if constexpr(use_avx2) {
// code of "functional_internal_code_using_avx2.h"
}
else {
// code of "functional_internal_code_without_avx2.h"
}
};
The code can be improved further by generalizing more, adding layers of abstractions that "just define the algorithm" instead of both the algorithm and platform-specific weirdness.
Another important argument against your solution is the fact that both functional_internal_code_using_avx2.h and functional_internal_code_without_avx2.h require special attention:
They do not build without example.h and it is not obvious without opening any of the files that they require it. So, specific flags/treatment when building the project have to be added, which is difficult to maintain as soon as you use more than one such functional_internal_code-files.
I am not sure what you the bigger picture is in your case, so whatever follows should be taken with a grain of salt.
Anyway: #include COULD happen anywhere in the code, BUT you could think of it as a way of separating code / avoiding redundancy. For definitions, this is already well covered by other means. For declarations, it is the standard approach.
Now, this #includes are placed at the beginning as a courtesy to the reader who can catch up more quickly on what to expect in the code to follow, even for #ifdef guarded code.
In your case, it looks like you want a different implementation of the same functionality. The to-go approach in this case would be to link a different portion of code (containing a different implementation), rather than importing a different declaration.
Instead, if you want to really have a different signature based on your #ifdef then I would not see a more effective way than having #ifdef in the middle of the code. BUT, I would not consider this a good design choice!
I define this as bad coding for me. It makes code hard to read.
My approach would be to create a base class as an abstract interface and create specialized implementations and then create the needed class.
E.g.:
class base_functions_t
{
public:
virtual void function1() = 0;
}
class base_functions_avx2_t : public base_functions_t
{
public:
virtual void function1()
{
// code here
}
}
class base_functions_sse2_t : public base_functions_t
{
public:
virtual void function1()
{
// code here
}
}
Then you can have a pointer to your base_functions_t and instanciate different versions. E.g.:
base_functions_t *func;
if (avx2)
{
func = new base_functions_avx2_t();
}
else
{
func = new base_functions_sse2_t();
}
func->function1();
As a general rule I would say that it's best to put headers that define interfaces first in your implementation files.
There are of course also headers that don't define any interfaces. I'm thinking mainly of headers that use macro hackery and are intended to be included one or more times. This type of header typically doesn't have include guards. An example would be <cassert>. This allows you to write code something like this
#define NDEBUG 1
#include <cassert>
void foo() {
// do some stuff
assert(some_condition);
}
#undef NDEBUG
#include <cassert>
void bar() {
assert(another_condition);
}
If you only include <cassert> at the start of your file you will have no granularity for asserts in your implementation file other than all on or all off. See here for more discussion on this technique.
If you do go down the path of using conditional inclusion as per your example then I would strongly recommend that you use an editor like Eclipse or Netbeans that can do inline preprocessor expansion and visualization. Otherwise the loss of locality that inclusion brings can severely hurt readability.
I am trying to compile a large C++ code (there are a few C files too) on a Linux cluster, having run it for some time on a Mac compiled with g++. On the cluster, I have to use either gcc/4.7.2 or intel/icpc (there is other software on the cluster that only works with those two compilers). I'm a newbie in dealing with compiling/linking problems, so no advice/tips is too simple.
I posted a question here a couple of days ago about a problem with using gcc/4.7.2. I haven't been able to resolve the problem, so now I'm trying icpc. Things have gone surprisingly well, but there is one problem I can't get past.
The problem is that I am getting errors related to "multiple definitions." These are associated with what seems to be a virtual function in a class that is inherited. I didn't write this code. There is a base class (Solver3), a derived class (Solver2), and another derived class (Solver1). The classes solve matrix equations. I can't tell which function is the problem because the error output is quite cryptic (see below; I have no function called "_fileno" and I can't find any generic definition of this term online). But the problem function is probably SolveWithSolver2 because it is the only function in the Solver1 class. I have no clue what could be wrong with it.
This is a bit over my head in terms of C++ knowledge and it is likely I'm making some beginner's mistake. For the past couple of days, I have used Google to search old forum posts. I have tried renaming what seems to be the problem function, I have tried inlining it. I get the same error. The code is very large and only a small part of it was written by me, so I can't post much of it. I will post what seems relevant and can add things if that would be helpful.
Here are the kinds of the errors I'm getting, starting from the first one (I have not posted all of the output):
/code/libraries/libsolver.a(Solver1.o): In
function _fileno(_IO_FILE*)': Solver1.cpp:(.text+0x0): multiple
definition of_fileno(_IO_FILE*)' main.o:main.cpp:(.text+0x1bc0):
first defined here
/code/libraries/libsolver.a(Solver2.o): In
function _fileno(_IO_FILE*)': Solver2.cpp:(.text+0x0): multiple
definition of_fileno(_IO_FILE*)' main.o:main.cpp:(.text+0x1bc0):
first defined here
/code/libraries/libsolver.a(Solver3.o):
In function _fileno(_IO_FILE*)':
Solver3.cpp:(.text+0x0): multiple definition of_fileno(_IO_FILE*)'
main.o:main.cpp:(.text+0x1bc0): first defined here
... And so on
Here is the Solver1 header code:
#ifndef SOLVER1
#define SOLVER1
#include "Solver2.h"
#include "ErrorHandler.h"
#ifdef SOLVER2
namespace code {
class Solver1 : public Solver2 {
public:
Solver1( );
//protected:
virtual void SolveWithSolver2( Matrix& A,
std::vector<double>& b,
std::vector<double>& x,
double tolerance );
private:
double pivot;
};
}
#endif
#endif
Here is the Solver2 header code:
#ifndef SOLVER2_H
#define SOLVER2_H
#include "Solver3.h"
#include "helper.h"
#ifdef SOLVER2
namespace code {
class Solver2: public Solver3 {
public:
Solver2 ();
//protected:
virtual void SolveWithSolver2(Matrix& A,
std::vector<double>& b,
std::vector<double>& x,
double tolerance) = 0;
private:
virtual void SolveEquation(Matrix& A,
std::vector<double>& b,
std::vector<double>& x,
stl_index unknowns);
double Residual(const Matrix& A,
const std::vector<double>& b,
std::vector< double >& x);
double Calculate(const SparseMatrix& A,
const std::vector<double >& b,
const std::vector< double >& x);
double residual;
};
}
#endif
#endif
Reply to Jakob:
Output of:
"grep _fileno" /usr/include/* -R
/usr/include/bits/dirent.h:#define d_fileno d_ino /* Backwards
compatibility. */ grep: warning:
/usr/include/c++/4.3/x86_64-suse-linux/32: recursive directory loop
/usr/include/dirent.h:#if (defined __USE_BSD || defined __USE_MISC) &&
!defined d_fileno /usr/include/dirent.h:# define d_ino d_fileno /*
Backward compatibility. */ /usr/include/lcms.h:# define fileno
_fileno /usr/include/libdwarf/libdwarf.h: Dwarf_Unsigned * /*ret_fileno*/, /usr/include/libio.h:#define _IO_DELETE_DONT_CLOSE
0x40 /* Don't call close(_fileno) on cleanup. */ /usr/include/libio.h:
int _fileno; /usr/include/linux/coda.h: u_int32_t d_fileno; /*
file number of entry */ /usr/include/linux/mtio.h: __kernel_daddr_t
mt_fileno; /* number of current file on tape */
/usr/include/sys/mtio.h: __daddr_t mt_fileno; /* Number of current
file on tape. */ /usr/include/X11/Xw32defs.h:#define fileno _fileno
Edit:
Using Jakob's suggestion about compiler flags (adding -Wl and -z) to my OPTIONS, my error output became much more clear; I got file names, line numbers, and particular errors.
I have now dealt with the problem, in the sense that I can compile that library. But to be honest, I don't really know why the compiler complained to begin with or why my solution worked. The problem involved preprocessor directives, which I confess I know little about. If anyone cares to speculate on what the issue was, it would be interesting to know. I have never run into needing ";" in preprocessor directives before.
This is what "fixed" things (sorry about the bold, large text; can't seem to turn that off):
define SOLVER_C_CONVERSION;
void __cdecl;
endif
This is what it looked like when it was a problem:
define SOLVER_C_CONVERSION void __cdecl
endif
So now that I've fixed that problem, I have one more library to deal with. It is throwing up all kinds of errors that g++ previously ignored. I may bother you all once more later on today if I can't solve them. I'm pretty sure the problem is with my makefile.
To solve the problem with the multiple definitions, the first step would probably be
tracking down the include dependencies,
using the '-M' or the '-H' compiler flag,
e.g. :
gcc -H {use correct include flags here: -I$( include path) } -c Solver1.cpp
This will show you a dependency tree (read top-down )
Then you could figure out, which of the files defines the _fileno symbol.
(e.g by using the grep command)
and finally you could try to understand, why _fileno is defined multiple times.
If you want a nicer dependency output, you could in general try to generate the include dependencies with doxygen.
Alternatively as a workaround you could use following link flags which will prevent the compilation process from failing in case of multiple definitions:
-Wl,-z,multiple
When I compile the program I am working on I get:
expected initializer before 'class'
error in my Class.h file. I looked up the error message on the internet, but couldn't find the exact error, although similar errors seem to be caused by missing semicolons but I don't see why I need one. This is the code the error points to, I have no other functions or classes before it.
class Account
{
public:
double dAccountBalance;
double dAccountChange(double dChange);
};
In the Class.cpp file the double dAccountChange(double dChange) function is defined. I don't think this is where the error is coming from but this is the code;
double Account::dAccountChange(double dChange)
{
dAccountBalance += dChange;
return 0.0;
}
When I change the code in Class.h to look like this,
;
class Account
{
public:
double dAccountBalance;
double dAccountChange(double dChange);
};
it doesn't generate an error message, but I can't work out why I need the semicolon before it as the only code I have before it are the following pre-processor lines.
#ifndef CLASS_H_INCLUDED
#define CLASS_H_INCLUDED
Any ideas on why the error is generated?
Most likely, in the header file you include immediately before class.h, you'll have something like:
class xyzzy {
int plugh;
}
without the closing semi-colon. That will make your code sequence:
class xyzzy {
int plugh;
}
class Account
{
public:
double dAccountBalance;
double dAccountChange(double dChange);
};
which is clearly invalid. Inserting a semi-colon in class.h before the first line will fix it, but it's clearly the wrong place to put it (since it means every header file you include immediately after that one would need a starting semicolon - also, it's part of the definition in the first header and should be there).
Now that may not be the exact code sequence but it will be something very similar, and the underlying reason will be a missing piece of text in the previous header.
You should go back and put it in the earlier include file.
For example, consider:
include1.h:
class xyzzy {
int plugh;
}
include2.h:
class twisty {
int little_passages;
};
main.cpp:
#include "include1.h"
#include "include2.h"
int main (void) {
return 0;
}
Compiling this produces:
include2.h:3: error: multiple types in one declaration
but placing the semicolon at the end of include1.h (or start of include2.h though we've already established that's not a good idea) will fix it.
The problem is in one of the other headers, one that you #include ahead of class.h.
If you show us the top of your main cpp file, it might give a clue.
Is it at all possible to parse C++ with incomplete declarations with clang with its existing libclang API ? I.e. parse .cpp file without including all the headers, deducing declarations on the fly. so, e.g. The following text:
A B::Foo(){return stuff();}
Will detect unknown symbol A, call my callback that deducts A is a class using my magic heuristic, then call this callback the same way with B and Foo and stuff. In the end I want to be able to infer that I saw a member Foo of class B returning A, and stuff is a function.. Or something to that effect.
context: I wanna see if I can do sensible syntax highlighting and on the fly code analysis without parsing all the headers very quickly.
[EDIT] To clarify, I'm looking for very heavily restricted C++ parsing, possibly with some heuristic to lift some of the restrictions.
C++ grammar is full of context dependencies. Is Foo() a function call or a construction of a temporary of class Foo? Is Foo<Bar> stuff; a template Foo<Bar> instantiation and declaration of variable stuff, or is it weird-looking 2 calls to overloaded operator < and operator > ? It's only possible to tell in context, and context often comes from parsing the headers.
What I'm looking for is a way to plug my custom convention rules. E.g. I know that I don't overload Win32 symbols, so I can safely assume that CreateFile is always a function, and I even know its signature. I also know that all my classes start with a capital letter and are nouns, and functions are usually verbs, so I can reasonably guess that Foo and Bar are class names. In a more complex scenario, I know I don't write side-effect-free expressions like a < b > c; so I can assume that a is always a template instantiation. And so on.
So, the question is whether it's possible to use Clang API to call back every time it encounters an unknown symbol, and give it an answer using my own non-C++ heuristic. If my heuristic fails, then the parse fails, obviously. And I'm not talking about parsing Boost library :) I'm talking about very simple C++, probably without templates, restricted to some minimum that clang can handle in this case.
I know the question is fairly old, but have a look here :
LibFuzzy is a library for heuristically parsing C++ based on Clang's
Lexer. The fuzzy parser is fault-tolerant, works without knowledge of
the build system and on incomplete source files. As the parser
necessarily makes guesses, the resulting syntax tree may be partially
wrong.
It is a sub-project from clang-highlight, an (experimental?) tool which seems to be no longer developed.
I'm only interested in the fuzzy parsing part and forked it on my github page where I fixed several minor issues and made the tool autonomous (it can be compiled outside clang's source tree). Don't try to compile it with C++14 (which G++ 6's default mode), because there will be conflicts with make_unique.
According to this page, clang-format has its own fuzzy parser (and is actively developed), but the parser was (is ?) more tighly coupled to the tool.
Unless you heavily restrict the code that people are allowed to write, it is basically impossible to do a good job of parsing C++ (and hence syntax highlighting beyond keywords/regular expressions) without parsing all the headers. The pre-processor is particularly good at screwing things up for you.
There are some thoughts on the difficulties of fuzzy parsing (in the context of visual studio) here which might be of interest: http://blogs.msdn.com/b/vcblog/archive/2011/03/03/10136696.aspx
Another solution which I think will suit more the OP than fuzzy parsing.
When parsing, clang maintains Semantic information through the Sema part of the analyzer. When encountering an unknown symbol, Sema will fallback to ExternalSemaSource to get some information about this symbol. Through this, you could implement what you want.
Here is a quick example how to set up it. It is not entirely functional (I'm not doing anything in the LookupUnqualified method), you might need to do further investigations and I think it is a good start.
// Declares clang::SyntaxOnlyAction.
#include <clang/Frontend/FrontendActions.h>
#include <clang/Tooling/CommonOptionsParser.h>
#include <clang/Tooling/Tooling.h>
#include <llvm/Support/CommandLine.h>
#include <clang/AST/AST.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/AST/RecursiveASTVisitor.h>
#include <clang/Frontend/ASTConsumers.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Tooling/CommonOptionsParser.h>
#include <clang/Tooling/Tooling.h>
#include <clang/Rewrite/Core/Rewriter.h>
#include <llvm/Support/raw_ostream.h>
#include <clang/Sema/ExternalSemaSource.h>
#include <clang/Sema/Sema.h>
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseAST.h"
#include <clang/Sema/Lookup.h>
#include <iostream>
using namespace clang;
using namespace clang::tooling;
using namespace llvm;
class ExampleVisitor : public RecursiveASTVisitor<ExampleVisitor> {
private:
ASTContext *astContext;
public:
explicit ExampleVisitor(CompilerInstance *CI, StringRef file)
: astContext(&(CI->getASTContext())) {}
virtual bool VisitVarDecl(VarDecl *d) {
std::cout << d->getNameAsString() << "#\n";
return true;
}
};
class ExampleASTConsumer : public ASTConsumer {
private:
ExampleVisitor visitor;
public:
explicit ExampleASTConsumer(CompilerInstance *CI, StringRef file)
: visitor(CI, file) {}
virtual void HandleTranslationUnit(ASTContext &Context) {
// de cette façon, on applique le visiteur sur l'ensemble de la translation
// unit
visitor.TraverseDecl(Context.getTranslationUnitDecl());
}
};
class DynamicIDHandler : public clang::ExternalSemaSource {
public:
DynamicIDHandler(clang::Sema *Sema)
: m_Sema(Sema), m_Context(Sema->getASTContext()) {}
~DynamicIDHandler() = default;
/// \brief Provides last resort lookup for failed unqualified lookups
///
/// If there is failed lookup, tell sema to create an artificial declaration
/// which is of dependent type. So the lookup result is marked as dependent
/// and the diagnostics are suppressed. After that is's an interpreter's
/// responsibility to fix all these fake declarations and lookups.
/// It is done by the DynamicExprTransformer.
///
/// #param[out] R The recovered symbol.
/// #param[in] S The scope in which the lookup failed.
virtual bool LookupUnqualified(clang::LookupResult &R, clang::Scope *S) {
DeclarationName Name = R.getLookupName();
std::cout << Name.getAsString() << "\n";
// IdentifierInfo *II = Name.getAsIdentifierInfo();
// SourceLocation Loc = R.getNameLoc();
// VarDecl *Result =
// // VarDecl::Create(m_Context, R.getSema().getFunctionLevelDeclContext(),
// // Loc, Loc, II, m_Context.DependentTy,
// // /*TypeSourceInfo*/ 0, SC_None, SC_None);
// if (Result) {
// R.addDecl(Result);
// // Say that we can handle the situation. Clang should try to recover
// return true;
// } else{
// return false;
// }
return false;
}
private:
clang::Sema *m_Sema;
clang::ASTContext &m_Context;
};
// *****************************************************************************/
LangOptions getFormattingLangOpts(bool Cpp03 = false) {
LangOptions LangOpts;
LangOpts.CPlusPlus = 1;
LangOpts.CPlusPlus11 = Cpp03 ? 0 : 1;
LangOpts.CPlusPlus14 = Cpp03 ? 0 : 1;
LangOpts.LineComment = 1;
LangOpts.Bool = 1;
LangOpts.ObjC1 = 1;
LangOpts.ObjC2 = 1;
return LangOpts;
}
int main() {
using clang::CompilerInstance;
using clang::TargetOptions;
using clang::TargetInfo;
using clang::FileEntry;
using clang::Token;
using clang::ASTContext;
using clang::ASTConsumer;
using clang::Parser;
using clang::DiagnosticOptions;
using clang::TextDiagnosticPrinter;
CompilerInstance ci;
ci.getLangOpts() = getFormattingLangOpts(false);
DiagnosticOptions diagnosticOptions;
ci.createDiagnostics();
std::shared_ptr<clang::TargetOptions> pto = std::make_shared<clang::TargetOptions>();
pto->Triple = llvm::sys::getDefaultTargetTriple();
TargetInfo *pti = TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto);
ci.setTarget(pti);
ci.createFileManager();
ci.createSourceManager(ci.getFileManager());
ci.createPreprocessor(clang::TU_Complete);
ci.getPreprocessorOpts().UsePredefines = false;
ci.createASTContext();
ci.setASTConsumer(
llvm::make_unique<ExampleASTConsumer>(&ci, "../src/test.cpp"));
ci.createSema(TU_Complete, nullptr);
auto &sema = ci.getSema();
sema.Initialize();
DynamicIDHandler handler(&sema);
sema.addExternalSource(&handler);
const FileEntry *pFile = ci.getFileManager().getFile("../src/test.cpp");
ci.getSourceManager().setMainFileID(ci.getSourceManager().createFileID(
pFile, clang::SourceLocation(), clang::SrcMgr::C_User));
ci.getDiagnosticClient().BeginSourceFile(ci.getLangOpts(),
&ci.getPreprocessor());
clang::ParseAST(sema,true,false);
ci.getDiagnosticClient().EndSourceFile();
return 0;
}
The idea and the DynamicIDHandler class are from cling project where unknown symbols are variable (hence the comments and the code).
OP doesn't want "fuzzy parsing". What he wants is full context-free parsing of the C++ source code, without any requirement for name and type resolution.
He plans to make educated guesses about the types based on the result of the parse.
Clang proper tangles parsing and name/type resolution, which means it must have all that background type information available when it parses. Other answers suggest a LibFuzzy that produces incorrect parse trees, and some fuzzy parser for clang-format about which I know nothing. If one insists on producing a classic AST, none of these solutions will produce the "right" tree in the face of ambiguous parses.
Our DMS Software Reengineering Toolkit with its C++ front end can parse C++ source without the type information, and produces accurate "ASTs"; these are actually abstract syntax dags where forks in trees represent different possible interpretations of the source code according to a language-precise grammar (ambiguous (sub)parses).
What Clang tries to do is avoid producing these multiple sub-parses by using type information as it parses. What DMS does is produce the ambiguous parses, and in (optional) post-parsing (attribute-grammar-evaluation) pass, collect symbol table information and eliminate the sub-parses which are inconsistent with the types; for well-formed programs, this produces a plain AST with no ambiguities left.
If OP wants to make heuristic guesses about the type information, he will need to know these possible interpretations. If they are eliminated in advance, he cannot straightforwardly guess what types might be needed. An interesting possibility is the idea of modifying the attribute grammar (provided in source form as part of the DMS's C++ front end), which already knows all of C++ type rules, to do this with partial information. That would be an enormous head start over building the heuristic analyzer from scratch, given that it has to know about 600 pages of arcane name and type resolution rules from the standard.
You can see examples of the (dag) produced by DMS's parser.
It's my first code with classes. the dev c++ compiler find 4 errors so i need a help. I think there's something wrong in my concept may be
This was the Header file "complex.h"
class complex{
public:
bool ReadComplex();
private:
double real;
double imag;
};
This is the .cpp file
#include "complex.h"
#include <iostream.h>
#include <math.h>
using namespace std;
bool complex::ReadComplex()
{ cout<<"Enter the real part";
cin>>real;
cout<<"Enter the imaginary part";
cin>>imag;
return true;
}
and i got 4 errors
C:/Dev-Cpp/include/c++/3.4.2/mingw32/bits/c++config.h:57: error: expected unqualified-id before "namespace"
C:/Dev-Cpp/include/c++/3.4.2/mingw32/bits/c++config.h:57: error: expected ,' or;' before "namespace"
C:/Dev-Cpp/include/c++/3.4.2/mingw32/bits/c++config.h:61: error: expected namespace-name before ';' token
C:/Dev-Cpp/include/c++/3.4.2/mingw32/bits/c++config.h:61: error: `' is not a namespace
Thanks a lot,
class definition should end with a ;
class complex
{
// ....
} ;
//^ missing semi-colon
You forgot the semicolon at the end of the class definition:
class complex{
}; //<------- here put a semicolon
Make sure you put the class in your own named namespace, or else not say using namespace std. There's a std::complex type, and although you don't include its header, implementors are allowed to include it themselves in any of the standard headers.
End your class definition with a semicolon: class complex { /* ... */ };
Don't use <iostream.h>. Use <iostream>. Things there are in the std:: namespace, by the way.
What's <Math.h>? Is it some 3rd party library you're using that's installed outside your project tree? If it's your own code or inside your project tree then use double quotes, not angle brackets. Double quotes ask the compiler to search for the code in your tree, whereas angle brackets ask the compiler to look in system directories.
Are you sure the standard math header won't do? Take a look at the <cmath> header.
You should also
make GetReal() and GeatImag() const functions. If the Get or Set counterparts don't do anything special you should throw them away and set the member data public. This because less code is less bugs.
You should take parameters as const references whenever it makes sense. Like in complex::Add(), for example, which should be a const function too if it doesn't change the object.
Your first code with classes should be:
class complex{
};
int main()
{
return(0);
}
Seriously. Get this to work, with no compiler warnings. Then add complexity a little at a time, and never add to code that doesn't work.