I was recently surprised to find Clang thinks the char type is considered unsigned in ARM architecture. For the sample code:
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include <iostream>
using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::tooling;
using namespace std;
static llvm::cl::OptionCategory MatchMatcherCategory("Options");
class MatchAlert : public MatchFinder::MatchCallback
{
public:
virtual void run(const MatchFinder::MatchResult &Result)
{
const VarDecl *VD = Result.Nodes.getNodeAs<VarDecl>("varDecl");
string var = VD->getNameAsString();
QualType QT = VD->getType();
if (QT->isCharType())
cout << var << " is a char\n";
if (QT->isUnsignedIntegerType())
cout << var << " is an unsigned integer type\n";
}
};
int main(int argc, const char** argv)
{
MatchFinder Finder;
MatchAlert varDeclAlert;
CommonOptionsParser OptionsParser(argc, argv, MatchMatcherCategory);
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());
Finder.addMatcher(varDecl().bind("varDecl"), &varDeclAlert);
Tool.run(newFrontendActionFactory(&Finder).get());
}
and the input file c.cpp:
char ch;
unsigned char unsignedCh;
when I run:
$ ./test c.cpp --
ch is a char
unsignedCh is a char
unsignedCh is an unsigned integer type
as expected. But when I run it with:
$ ./test --extra-arg=--target=arm-none-eabi c.cpp --
ch is a char
ch is an unsigned integer type
unsignedCh is a char
unsignedCh is an unsigned integer type
So my question is why? I tried it with several other architectures, and always see char as a signed value.
I’m running on an Ubuntu Linux system with:
$ ./test -version
LLVM version 12.0.1
Optimized build.
Default target: x86_64-unknown-linux-gnu
Host CPU: skylake