如何知道IntegerLiteral是否来自Clang的十进制或八进制表示?

时间:2014-07-31 13:39:38

标签: c++ c clang

如您所知,Clang库中的整数值由IntegerLiteral class处理。

但是,作为行动的问题,这两项任务似乎没有区别:

int i,j;
// i is assigned 42 with octal representation (052)
i = 052; 
//j is assigned 42 with decimal representation (42)
j = 42;

AST-dump产生相同的树:

|-DeclStmt 0x1cbc5b0 <line:2:2, col:9>
| |-VarDecl 0x1cbc4d0 <col:2, col:6> i 'int'
| `-VarDecl 0x1cbc540 <col:2, col:8> j 'int'
|-BinaryOperator 0x1cbc610 <line:4:2, col:6> 'int' lvalue '='
| |-DeclRefExpr 0x1cbc5c8 <col:2> 'int' lvalue Var 0x1cbc4d0 'i' 'int'
| `-IntegerLiteral 0x1cbc5f0 <col:6> 'int' 42
|-BinaryOperator 0x1cbc680 <line:5:2, col:6> 'int' lvalue '='
| |-DeclRefExpr 0x1cbc638 <col:2> 'int' lvalue Var 0x1cbc540 'j' 'int'
| `-IntegerLiteral 0x1cbc660 <col:6> 'int' 42

我想提出一些警告,因为使用八进制表示会被危险地误解。我可以区分Clang解析这两种表示的方式吗?

3 个答案:

答案 0 :(得分:2)

致电clang::Lexer::getSpelling,将SourceLocation传递给您IntegerLiteral。然后,您可以对八进制或您感兴趣的任何其他拼写属性进行手动测试(例如,查找前导'0'后跟数字)。手动执行此检查还可以让您正确地获得一些特殊情况 - 例如,0在技术上是八进制文字,但您可能不想将其视为方式。

答案 1 :(得分:0)

如果整数常量以八进制或十进制方式给出,那么它只是一个句法事实。编译后,整数文字将转换为相同的二进制数。在正数的情况下,表示由标准精确地表示,是存储的整数值的精确二进制表示。

因此,在任何情况下,源程序中基数的信息(八进制,十进制,十六进制)都不会存储在任何地方,因此在执行环境中无法了解它的任何信息。

我同意 Deduplicator 的评论:您需要预处理源代码本身以“查看”此信息。

另一种选择可能是您在第一种方法中不使用int值,而是使用字符串。

  char *s_val1 = "052";  
  char *s_val2 = "42";  
  if (radix(s_val1) == 8)   // You can write some function radix() to recognize the radix
      printf("%s is octal", s_val1);

  int val1 = octalstr_to_int(s_val1);  // You can write some string-to-integer convertion functions

答案 2 :(得分:0)

在无法实现 Richard Smith 给出的答案之后,我发现了一种非常讨厌的方法(并且它不适用于MACROS),但万一,这是我的(解决方案:

bool VisitIntegerLiteral(IntegerLiteral * intLiteral){
    // Source Location of current int literal
    SourceLocation loc = intLiteral->getLocation();
    // Source manager associated
    SourceManager &SM = _carrier->getSourceManager();
    // Get first char and second char of the integer literal (getCharacterData returns the whole code from the SourceLocation until the end of code)
    char first_char = SM.getCharacterData(loc,nullptr)[0];
    char second_char= SM.getCharacterData(loc,nullptr)[1];
    // If first character is 0
    if(first_char == '0'){
        // If second character is also a number
        if(second_char == '1' || second_char == '2' || second_char == '3' || second_char == '4' || second_char == '5' || second_char == '6' || second_char == '7' || second_char == '8' || second_char == '9'){
            cout << "This is an octal value" << endl;
        }
    }
    return true;
}