C++ Random errors in a copied library - c++

I copied a Big Int Library into my code and I'm having random errors in one of the classes. (The code is older)
One of my errors is in a define statement, not really sure how these work.
Everything under "tmpthis;" is giving an error.
#define DTRT_ALIASED(cond, op) \
if (cond) {\
BigUnsigned tmpThis;
tmpThis.op; //Error: no storage class or type specifier
*this = tmpThis; //Error: *this expected an identifier Error: No suitable conversion from "BigUnsigned" to "int" exists.
return; // Error: expected a declaration
} \
On top of that there are a few random if and for statements with the error "expected a declaration" and some variables with the error " no storage class or type specifier"
NOTE: these random errors also had instances where they were not errors also, it was inconsistent.

A bare-bones fix to the macro is:
#define DTRT_ALIASED(cond, op) \
if (cond) { \
BigUnsigned tmpThis; \
tmpThis.op; \
*this = tmpThis; \
return; \
}
This stands a chance of compiling when used in a function that doesn't return a value, if the reference to op in tmpThis.op makes sense to the compiler. It is somewhat peculiar (and limited) code, but there might be a use for it.

Related

how to solve: error: global qualification of class name is invalid before '{' token

I'm trying to build https://android.googlesource.com/device/generic/vulkan-cereal
but have run into an error that seems to only happen with GCC (v8.3 is what I have to work with).
There are related questions, but I still don't understand what's going on well enough to fix the issue:
Global qualification in base specifier
Global qualification in a class declarations class-head
The code:
https://android.googlesource.com/device/generic/vulkan-cereal/+/refs/heads/master/stream-servers/vulkan/vk_fn_info.h
#define REGISTER_VK_FN_INFO(coreName, allNames) \
struct coreName; \
template <> \
struct ::vk_util::vk_fn_info::GetVkFnInfo<coreName> { \
static constexpr auto names = std::make_tuple allNames; \
using type = PFN_vk##coreName; \
};
REGISTER_VK_FN_INFO(GetPhysicalDeviceProperties2,
("vkGetPhysicalDeviceProperties2KHR", "vkGetPhysicalDeviceProperties2"))
The Error:
vulkan-cereal/stream-servers/vulkan/vk_fn_info.h:31:57: error: global qualification of class name is invalid before '{' token
struct ::vk_util::vk_fn_info::GetVkFnInfo<coreName> { \
^
/vulkan-cereal/stream-servers/vulkan/vk_fn_info.h:36:1: note: in expansion of macro 'REGISTER_VK_FN_INFO'
REGISTER_VK_FN_INFO(GetPhysicalDeviceProperties2,
^~~~~~~~~~~~~~~~~~~
What can I do to get this to build?
The global qualifier is the two colons at the front:
struct ::vk_util::vk_fn_info::GetVkFnInfo<coreName> {
^^
But the answer was to remove all qualifiers:
struct ::vk_util::vk_fn_info::GetVkFnInfo<coreName> {
^^^^^^^^^^^^^^^^^^^^^^^
So it becomes:
#define REGISTER_VK_FN_INFO(coreName, allNames) \
struct coreName; \
template <> \
struct GetVkFnInfo<coreName> { \
static constexpr auto names = std::make_tuple allNames; \
using type = PFN_vk##coreName; \
};
The trick was that this revealed knock-on errors caused by the macro being improperly used outside the namespaces in another file:
vk_util_unittest.cpp:28:25: error: expected constructor, destructor, or type conversion before '(' token
REGISTER_VK_FN_INFO_TEST(GfxstreamTestFunc, ("vkGfxstreamTestFunc", "vkGfxstreamTestFuncGOOGLE",
The final change required fixing the namespaces in vk_util_unittest.cpp so that they matched the ones in vk_fn_info.h
As an alternative, I found that the macro could be used outside the namespace as long as it was fully qualified (excluding the invalid global qualification):
#define REGISTER_VK_FN_INFO_EXTERN(coreName, allNames) \
struct coreName; \
template <> \
struct vk_util::vk_fn_info::GetVkFnInfo<coreName> { \
static constexpr auto names = std::make_tuple allNames; \
using type = PFN_vk##coreName; \
};
But this prevented it from being used within the namespace. Two separate macros would be needed to satisfy use within and without the namespace.

static_assert inside a macro throwing compile time errors even when it shouldn't (Visual Studio)

tl;dr
When I try to compile this code, Visual Studio throws a compile time error for very static_assert, regardless of wheter it should, and then also one "active error" for the only one that should. This is an issue with my code, or with Visual Studio?
Visual Studio Version
Microsoft Visual Studio Community 2019
Version 16.10.2
#include <memory>
struct Node {};
struct A : Node {};
struct B : Node {};
#define cast_to_A(ptr) ([&] () { \
static_assert( \
std::is_same<std::shared_ptr<Node>, decltype(ptr)>::value, \
"Cannot cast to an A pointer." \
); \
return std::static_pointer_cast<A>(ptr); \
})()
#define cast_to_B(ptr) ([&] () { \
static_assert( \
std::is_same<std::shared_ptr<Node>, decltype(ptr)>::value, \
"Cannot cast to a B pointer." \
); \
return std::static_pointer_cast<B>(ptr); \
})()
int main() {
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
auto aAsNode = std::static_pointer_cast<Node>(a);
auto bAsNode = std::static_pointer_cast<Node>(b);
auto a1 = cast_to_A(aAsNode); // Expected: No error, Actual: "Cannot cast to an A pointer."
auto b1 = cast_to_B(bAsNode); // Expected: No error, Actual: "Cannot cast to an B pointer."
auto badCast = cast_to_A(b); // Expected & Actual: "Cannot cast to an A pointer."
return 0;
}
Context
In a personal project, I have a node struct from which a bunch of child structs inherit. Throughout the program I cast from std::shared_ptr<Node> to std::shared_ptr<Child> and vice-versa using std::static_pointer_cast. Somewhere in my program I have compile time errors where I'm acidentally trying to convert from one sibling pointer to another. However, the error is attriubted to code within std::static_pointer_cast (line 1925 of <memory>), and as it isn't a runtime error I can't move up the call stack to find where my bad call is.
As it happens, the code for my structs is procedurally generated by a python script I wrote. My attempted solution was to generate a macro for each struct (like seen in the toy example), then I just did a regex search/replace to replace all my std::static_pointer_cast calls with the appropriate macro.
The issue I have is that recreated in the toy example above. Visual Studio puts a red line under the macro "calls" that I would expect to fail (so I've actually found the bug now), but for every single use of the macro it also throws a compile time error from the static_assert, even when (to my understanding) it shouldn't fail. It doesn't put a red line under those "calls" though, so I'm unsure if this is a Visual Studio bug.
Looking around online saw that std::is_same can be quite particular about what counts as the same type or not. The variable given as the marco argument get's passed to the static_assert by reference (as it passes through the lambda's [&] capture), so I wondered if this was throwing it off. But I couldn't figure out any way to tweak the types to make it work.
Thanks in advance for any help! Any pointers or tips are much appreciated!
#1201ProgramAlarm answered in the comments. The solution was to use std::remove_reference to remove the reference added to the ptr when it is passed into the lambda. The final macro was:
#define cast_to_A(ptr) ([&] () { \
static_assert( \
std::is_same<std::shared_ptr<Node>, std::remove_reference<decltype(ptr)>::type>::value, \
"Cannot cast to an A pointer." \
); \
return std::static_pointer_cast<A>(ptr); \
})()
Now only the expected "bad cast" throws an error

Uninitialized register variable warning

I was working with a old codebase where I encountered few line of code which was causing lot of repeated warnings during compilation.
#define EXAMPLE(_ptr) \
{ \
register uintptr_t *__sp __asm__("sp"); \
(_ptr[0]) = (uintptr_t) __sp; \
asm volatile("sw $a0,%0" : "=m" (_ptr[1])); \
//SOME OTHER CODE HERE
}
the warning was:
warning: ‘__sp’ may be used uninitialized in this function
Can anyone help me in understanding what is happening in this code block and how to remove this warning.

Compiler warning: suggest parentheses around arithmetic in operand of '|'

I have gone through all other similar issues, and yet I cannot understand why I am getting this error :
warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
&((~((PERIPHS_IO_MUX_FUNC)<<(PERIPHS_IO_MUX_FUNC_S)))) \
I am using xtensa-gcc. Following is the code (from ESP8266 SDK) :
#define PIN_FUNC_SELECT(PIN_NAME, FUNC) do { \
WRITE_PERI_REG(PIN_NAME, \
(READ_PERI_REG(PIN_NAME)) \
&((~((PERIPHS_IO_MUX_FUNC)<<(PERIPHS_IO_MUX_FUNC_S)))) \
|((((FUNC&BIT2)<<(2))|(FUNC&0x3))<<(PERIPHS_IO_MUX_FUNC_S)) ); \
} while (0)
The "&" and "|" leading on the last two lines both are at the same level of parentheses. The compiler is warning you that there can be some confusion by developers regarding precedence.

Setup type as macro parameter returns error: expected unqualified-id before string constant

I am trying to do some code generation.
When I want to set type of returning value with the parameter compile fails.
Why compiler returns me error?
#define MODULE_GETTER(module_type, interface_type) \
public: \
static #interface_type * Instance##interface_type (void) \
{ \
return NULL;\
}
class MyModuleType :
public IMyModuleInterface
{
MODULE_GETTER(MyModuleType,IMyModuleInterface)
private:
...
};
When I change static #interface_type * into static int * or any other predefined type, code compiles without error.
What am I doing wrong?
Within a macro definition, # is the stringification operator, which wraps its operand in quotes to make a string literal; so the macro expands into
static "IMyModuleInterface" * InstanceIMyModuleInterface (void)
which is nonsense. Get rid of the rogue # and it should compile.