3
3
#include < clang/Basic/IdentifierTable.h>
4
4
#include < clang/Lex/LiteralSupport.h>
5
5
#include < clang/Lex/MacroInfo.h>
6
+ #include < llvm/ADT/APInt.h>
7
+ #include < llvm/ADT/APSInt.h>
6
8
7
9
DefineFinder::DefineFinder (IR &ir, const clang::CompilerInstance &compiler,
8
10
clang::Preprocessor &pp)
@@ -76,18 +78,27 @@ void DefineFinder::MacroUndefined(const clang::Token &MacroNameTok,
76
78
}
77
79
78
80
void DefineFinder::addNumericConstantDefine (const std::string ¯oName,
79
- const std::string & literal,
81
+ std::string literal,
80
82
const clang::Token *finalToken) {
81
83
clang::NumericLiteralParser parser (literal, finalToken->getLocation (), pp);
82
84
std::string type;
83
85
if (parser.isIntegerLiteral ()) {
86
+ std::replace (literal.begin (), literal.end (), ' l' , ' L' );
84
87
if (parser.isLongLong ) {
85
- return ;
86
- }
87
- if (parser.isLong ) {
88
+ /* literal has `LL` ending but `long long` is represented as
89
+ * `Long` in Scala Native */
90
+ literal = literal.substr (0 , literal.length () - 1 ); // remove last L
91
+ type = " native.CLongLong" ;
92
+ } else if (parser.isLong ) {
93
+ /* literal already has `L` ending */
88
94
type = " native.CLong" ;
89
95
} else {
90
- type = " native.CInt" ;
96
+ /* literal may not have `l` or `ll` ending but still be of long type
97
+ * NumericLiteralParser does not recognize that 10000000000
98
+ * is a long value.
99
+ * Therefore we need to check that value fits into certain number
100
+ * of bits. */
101
+ getTypeOfIntLiteralWithoutEnding (parser, literal, type);
91
102
}
92
103
} else {
93
104
if (parser.isFloat ) {
@@ -99,3 +110,45 @@ void DefineFinder::addNumericConstantDefine(const std::string ¯oName,
99
110
ir.addLiteralDefine (macroName, literal, type);
100
111
}
101
112
}
113
+
114
+ /* *
115
+ * Check if literal without `l` or `ll` ending fits into int or long variable.
116
+ *
117
+ * Set `literal` and `type` parameters.
118
+ */
119
+ void DefineFinder::getTypeOfIntLiteralWithoutEnding (
120
+ clang::NumericLiteralParser parser, std::string &literal,
121
+ std::string &type) {
122
+
123
+ bool isSigned = llvm::APSInt (literal).isSigned ();
124
+
125
+ llvm::APInt intSignedVal (4 * 8 , 0 , false );
126
+ llvm::APInt intUnsignedVal (4 * 8 - 1 , 0 , false );
127
+ /* it does not matter if APInt instance is signed or not
128
+ * because when calling GetIntegerValue it will check if unsigned value may
129
+ * fit into the full width defined in APInt */
130
+ if ((!isSigned && !parser.GetIntegerValue (intUnsignedVal)) ||
131
+ (isSigned && !parser.GetIntegerValue (intSignedVal))) {
132
+ type = " native.CInt" ;
133
+ } else {
134
+ llvm::APInt longSignedVal (8 * 8 , 0 , false );
135
+ llvm::APInt longUnsignedVal (8 * 8 - 1 , 0 , false );
136
+ if ((!isSigned && !parser.GetIntegerValue (longUnsignedVal)) ||
137
+ (isSigned && !parser.GetIntegerValue (longSignedVal))) {
138
+ type = " native.CLong" ;
139
+ literal = literal + " L" ;
140
+ } else {
141
+ llvm::errs () << " Waring: integer value does not fit into 8 bytes: "
142
+ << literal << " \n " ;
143
+ llvm::errs ().flush ();
144
+ /* *
145
+ * `long long` value has mostly the same size as `long`.
146
+ * Moreover in Scala Native the type is represented as `Long`:
147
+ * @code
148
+ * type CLongLong = Long
149
+ * @endcode
150
+ * Therefore the case of `long long` is not considered here.
151
+ */
152
+ }
153
+ }
154
+ }
0 commit comments