If i understand correctly, static analysis can guess what values a variable can have, and deduce, for example, what path in the control flow graph will never be executed.
I have an array of constants strings CStr. A method GetValue takes an index in parameters and do some computation to find the actual index in CStr array and return the const string pointed at that index.
edit: The actual index is unique and constant for each parameter given to GetValue
Can static analysis guess that GetValue(x) will have a constant value ? If yes, how is it done ?
"Can static analysis guess that GetValue(x) will have a constant value ?"
That totally depends on the capabilities and quality of your static code analysis tool.
From theory that's possible to detect, yes.
If you meant what the compiler can deduce about constant expressions, it also depends on the compiler's actual implementation.
The best hint you can give it, is using the constexpr keyword, e.g.
constexpr int GetValue(int x);
"If yes, how is it done ?"
That's a very broad field, and hard to give a concise answer here.
Basically a static code analysis tool keeps track about the call references of particular functions. If the result of these functions can be deduced being a value that is specified at compile time (e.g. due to static initialization), the actual valid size/index of an accessed address from a calling function is known, and can be marked as issue if it's out of bounds.
Related
I have a compile-time string class that helps programs compute various relevant things at compile time, such as hash results and a quick lookup table for find, which is constructed like this:
"hello"_constexpr_str;
Also, my string class supports construction from this type, which allows for fast hash and fast find and avoids unnecessary data copying, like this.
defs::string string = "hello"_constexpr_str;
Of course, my string class also supports building from const char_T*
Now here's the problem!
I want to use the constexpr method automatically when my string class is constructed with compile-time constants like string("hell word!") rather than ugly but strong string("hell word!"_constexpr_str)
In other words, I want string("hell word!") to automatically become string("hell word!"_constexpr_str) in compile-time to calculate the information about the constant string and put it in constant state storage, so that all my string class has to do is hold a pointer to constexpr_str_t
//Draft Code
#if defined(__cpp_if_consteval)
#define if_in_consteval if consteval
#else
#define if_in_consteval if constexpr(0)
#endif
constexpr string_t(const constexpr_str_t&str)noexcept;//save a pointer to constexpr_str_t
string_t(const char_T* str)noexcept{
if_in_consteval{
constexpr constexpr_str_t constexpr_str(str);
construct[this](constexpr_str);
}
else{
construct[this](string_view_t(str));
}
}
What do I do to achieve this?
If I understood your question now after the discussion in the comments correctly, you have a operator""_constexpr_str which is marked consteval and returns a string-view-like type constexpr_str_t with some additional information attached based on the contents of the string.
You then have a function taking an (ordinary) string literal as argument with overloads taking either constexpr_str_t or const char*. You basically want the const char* overload to only be chosen when the argument is not a constant expression. Otherwise the constexpr_str_t overload should be chosen and constructed at compile-time (i.e. via consteval) so that the extra information can be attached at compile-time.
This cannot work however, because it is impossible to overload on consteval. Whether or not a consteval function is called depends only on the type of the argument. It is not possible to distinguish between constant expression arguments and non-constant expression arguments.
Trying to determine whether a function argument is a constant expression inside a function is also impossible. Functions are compiled individually. They are not compiled twice depending on whether or not the argument is a constant expression.
The only thing possible is to change behavior based on whether the whole expression that the function call is used in is a context requiring a constant expression. That is what if consteval is for. But if you are making a decision based on such a scenario, you don't need
constexpr constexpr_str_t constexpr_str(str);
You can simply do the calculation for the additional properties of the string there as if at runtime and mark the function constexpr. If used in a context requiring a constant expression it will be evaluated at compile-time.
If you want to enforce this even if the call doesn't happen in a context requiring a constant expression, then it is impossible.
You can however write a macro which tests whether an expression is a constant expression and then conditionally calls either a consteval function or a non-consteval function. It is just impossible through a function call.
You can use the C++20 std::is_constant_evaluated() function found in the <type_traits> header. It detects whether a function call occurs within a constant-evaluated context.
I'm looking for some construct that can detect whether a local expression is a constant expression, or whether it's not, that can be used in a static_assert declaration.
In code:
int main()
{
constexpr int i = 1;
if constexpr(i) {}
static_assert(is_constexpr(i));
int j = 1;
//if constexpr(j) {} // error: 'j' is not usable in a constant expression
static_assert(!is_constexpr(j));
}
The is_constexpr here can be a macro, a class (then probably with other syntax), or a function. How to make is_constexpr(i) return true/true_type and, conversely, is_constexpr(j) return false/false_type?
I tried a lot of the solutions available here on SO (also using old-school SFINAE) without success. I can edit in the links and my failed attempts if required.
Playground on godbolt here
The problem is that parameters (like t) are not constant expressions. For example, we cannot use t as a template non-type parameter, or as a size of a built-in array.
This means that some expression say some_expr( t ) that contains(involves) the subexpression t is itself not a constant expression, either.
Can is_constexpr be a function?
The simple fact that you write is_constexpr(i) means that you're looking for a function of type bool(auto); but you also want to be able to pass it constexpr arguments or non-constexpr arguments, so for sure it can't be consteval otherwise it would error when called in the latter scenario; so you can at most make it constexpr. However, there's no such a thing (yet?) as a constexpr function parameter, so as soon as you pass something to that constexpr function you have no way to detect whether or not the argument was a constant expression at the call site.
Can is_constexpr be a meta-function?
The other opportunity would be to use a metafunction, but how would you expect to call it? If you expect is_constexpr<i>, i.e. passing the entity you are querying as a template argument, that would be clearly only possible if i is constexpr; if you go for is_constexpr<decltype(x)>, you are expecting that decltype(x) contains some info about the constexpr-ness of x, but that's not the case, as constexpr/consteval are not part of the type of an expression.
Do you really need it?
This, I believe, means that whenever you ask whether an expression is a constant expression, you can always find the answer by looking at the code before that expression, and that answer will not depend on any boolean condition, not even a constexpr condition.
In other words, I believe (and happy to be proved wrong), there's no way for an expression appearing in a C++ program to be constexpr or not in the same line of code depending on the path that leads there.
Do we really have a usecase?
I agree that this is likely an XY problem.
So I challenge you to write an example where a given C++ expression of your choice appearing at a certain line of code is constexpr across one branch of execution and non-constexpr across another branch. And the branches can also be compile-time (well, given your question, you were not asking about non-compile-time branching, so in the previous sentence you can can also be are).
I have a hash function, I want to implement it with C++20 consteval to make sure the inputs I want to be evaluated at compile time will be done before runtime. That's for the constants and hardcoded content. However, later I need to compare them with runtime/dynamic variables, for the equals() to work I have to calculate the hash of the runtime variable and I need to invoke the very same algorithm from runtime.
The instinct is the implement it twice (one for compile-time and one for runtime), but it feels wrong to duplicate the code when it's in essence the same algorithm/code. Is there a smarter way (template variable or something) to have one algorithm which can be instantiated for both purposes as needed?
The C++14 and higher have a lot of great features and wondering if something slipped my mind. Preferably I would like to use the pure C++ features and avoid helper libs like std boost etc...
How to guarantee compile-time evaluation of algorithm while allowing runtime invocation as well
Write your function as a constexpr one, and then, if you want to guarantee a particular result is done at compile-time, write the result into a constexpr variable:
constexpr int f(...) { ... }
constexpr int compile_time_result = f(...);
You will get an error if the result couldn't be computed at compile-time.
If you don't care, take out the constexpr of the variable:
int maybe_runtime_result = f(...);
The basic question:
Edit: v-The question-v
class foo {
public:
constexpr foo() { }
constexpr int operator()(const int& i) { return int(i); }
}
Performance is a non-trivial issue. How does the compiler actually compile the above? I know how I want it to be resolved, but how does the specification actually specify it will be resolved?
1) Seeing the type int has a constexpr constructor, create a int object and compile the string of bytes that make the type from memory into the code directly?
2) Replace any calls to the overload with a call to the 'int's constructor that for some unknown reason int doesn't have constexpr constructors? (Inlining the call.)
3) Create a function, call the function, and have that function call 'int's consctructor?
Why I want to know, and how I plan to use the knowledge
edit:v-Background only-v
The real library I'm working with uses template arguments to decide how a given type should be passed between functions. That is, by reference or by value because the exact size of the type is unknown. It will be a user's responsibility to work within the limits I give them, but I want these limits to be as light and user friendly as I can sanely make them.
I expect a simple single byte character to be passed around in which case it should be passed by value. I do not bar 300mega-byte behemoth that does several minuets of recalculation every time a copy constructor is invoked. In which case passing by reference makes more sense. I have only a list of requirements that a type must comply with, not set cap on what a type can or can not do.
Why I want to know the answer to my question is so I can in good faith make a function object that accepts this unknown template, and then makes a decision how, when, or even how much of a object should be copied. Via a virtual member function and a pointer allocated with new is so required. If the compiler resolves constexpr badly I need to know so I can abandon this line of thought and/or find a new one. Again, It will be a user's responsibility to work within the limits I give them, but I want these limits to be as light and user friendly as I can sanely make them.
Edit: Thank you for your answers. The only real question was the second sentence. It has now been answered. Everything else If more background is required, Allow me to restate the above:
I have a template with four argument. The goal of the template is a routing protocol. Be that TCP/IP -unlikely- or node to node within a game -possible. The first two are for data storage. They have no requirement beyond a list of operators for each. The last two define how the data is passed within the template. By default this is by reference. For performance and freedom of use, these can be changed define to pass information by value at a user's request.
Each is expect to be a single byte long. They could in the case of metric for a EIGRP or OSFP like protocol the second template argument could be the compound of a dozen or more different variable. Each taking a non-trival time to copy or recompute.
For ease of use I investigate the use a function object that accepts the third and fourth template to handle special cases and polymorphic classes that would fail to function or copy correctly. The goal to not force a user to rebuild their objects from scratch. This would require planning for virtual function to preform deep copies, or any number of other unknown oddites. The usefulness of the function object depends on how sanely a compiler can be depended on not generate a cascade of function calls.
More helpful I hope?
The C++11 standard doesn't say anything about how constexpr will be compiled down to machine instructions. The standard just says that expressions that are constexpr may be used in contexts where a compile time constant value is required. How any particular compiler chooses to translate that to executable code is an implementation issue.
Now in general, with optimizations turned on you can expect a reasonable compiler to not execute any code at runtime for many uses of constexpr but there aren't really any guarantees. I'm not really clear on what exactly you're asking about in your example so it's hard to give any specifics about your use case.
constexpr expressions are not special. For all intents and purposes, they're basically const unless the context they're used in is constexpr and all variables/functions are also constexpr. It is implementation defined how the compiler chooses to handle this. The Standard never deals with implementation details because it speaks in abstract terms.
Is there a simple way to take the general arguments of a function (Pointer, Array, Integer) and get the values backing the expression, when writing a custom checker? As in, I match against a function such as:
Pointer p;
Integer i;
CallSite f("func");
if(MATCH( f(p,i) ))
//get function arguments
Is there a simple way of getting the values backing p and i? Thanks.
**Language is C++ to make a custom checker
There is no way to get run-time value from these variables statically.
Maybe it's more accurate to say that this is beyond the scope of what a simple static analysis checker can do.
The exception would be if you are passing a literal value or constant.