Repository: ericsson/codechecker
Issue: Wrong handling of builtin includes during ctu collect phase

Clang does not find its own builltin includes during ctu collect phase.

```
[ERROR] [10:45] - Error generating AST.

command:

/home/compass/srv/codecheckernightlyctu/workspace/install/CodeChecker/cc_bin/clang -isystem /usr/include/c++/4.8 -isystem /usr/include/x86_64-linux-gnu/c++/4.8 -isystem /usr/include/c++/4.8/backward -isystem /usr/lib/gcc/x86_64-linux-gnu/4.8/include -isystem /usr/local/include -isystem /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed -isystem /usr/include/x86_64-linux-gnu -isystem /usr/include -resource-dir /home/compass/srv/codecheckernightlyctu/workspace/install/CodeChecker/include -isystem /home/compass/srv/codecheckernightlyctu/workspace/install/CodeChecker/include -c -x c++  -DHAVE_CONFIG_H -DXERCES_BUILDING_LIBRARY -I/home/compass/srv/codecheckernightlyctu/source/xerces-c-3.1.1/src -I/home/compass/srv/codecheckernightlyctu/source/xerces-c-3.1.1 -I/home/compass/srv/codecheckernightlyctu/source/xerces-c-3.1.1/src/xercesc/util -O2 -msse2 -fPIC -DPIC /home/compass/srv/codecheckernightlyctu/source/xerces-c-3.1.1/src/xercesc/validators/common/CMBinaryOp.cpp -emit-ast -w -o /home/compass/srv/codecheckernightlyctu/workspace/old_reports/ctu-dir/x86_64/ast/home/compass/srv/codecheckernightlyctu/source/xerces-c-3.1.1/src/xercesc/validators/common/CMBinaryOp.cpp.ast

stderr:

In file included from /home/compass/srv/codecheckernightlyctu/source/xerces-c-3.1.1/src/xercesc/validators/common/CMBinaryOp.cpp:29:
In file included from /home/compass/srv/codecheckernightlyctu/source/xerces-c-3.1.1/src/xercesc/validators/common/CMBinaryOp.hpp:25:
In file included from /home/compass/srv/codecheckernightlyctu/source/xerces-c-3.1.1/src/xercesc/validators/common/CMNode.hpp:28:
In file included from /home/compass/srv/codecheckernightlyctu/source/xerces-c-3.1.1/src/xercesc/validators/common/CMStateSet.hpp:41:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.8/include/emmintrin.h:35:
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:101:19: error: use of undeclared identifier '__builtin_ia32_addss'
  return (__m128) __builtin_ia32_addss ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:107:19: error: use of undeclared identifier '__builtin_ia32_subss'
  return (__m128) __builtin_ia32_subss ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:113:19: error: use of undeclared identifier '__builtin_ia32_mulss'
  return (__m128) __builtin_ia32_mulss ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:119:19: error: use of undeclared identifier '__builtin_ia32_divss'; did you mean '__builtin_ia32_minss'?
  return (__m128) __builtin_ia32_divss ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:113:19: note: '__builtin_ia32_minss' declared here
  return (__m128) __builtin_ia32_mulss ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:157:19: error: use of undeclared identifier '__builtin_ia32_addps'; did you mean '__builtin_ia32_haddps'?
  return (__m128) __builtin_ia32_addps ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:157:19: note: '__builtin_ia32_haddps' declared here
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:163:19: error: use of undeclared identifier '__builtin_ia32_subps'; did you mean '__builtin_ia32_hsubps'?
  return (__m128) __builtin_ia32_subps ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:163:19: note: '__builtin_ia32_hsubps' declared here
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:169:19: error: use of undeclared identifier '__builtin_ia32_mulps'
  return (__m128) __builtin_ia32_mulps ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:175:19: error: use of undeclared identifier '__builtin_ia32_divps'; did you mean '__builtin_ia32_minps'?
  return (__m128) __builtin_ia32_divps ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:119:19: note: '__builtin_ia32_minps' declared here
  return (__m128) __builtin_ia32_divss ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:213:10: error: use of undeclared identifier '__builtin_ia32_andps'; did you mean '__builtin_ia32_haddps'?
  return __builtin_ia32_andps (__A, __B);
         ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:157:19: note: '__builtin_ia32_haddps' declared here
  return (__m128) __builtin_ia32_addps ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:219:10: error: use of undeclared identifier '__builtin_ia32_andnps'
  return __builtin_ia32_andnps (__A, __B);
         ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:225:10: error: use of undeclared identifier '__builtin_ia32_orps'
  return __builtin_ia32_orps (__A, __B);
         ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:231:10: error: use of undeclared identifier '__builtin_ia32_xorps'
  return __builtin_ia32_xorps (__A, __B);
         ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:259:19: error: use of undeclared identifier '__builtin_ia32_movss'
  return (__m128) __builtin_ia32_movss ((__v4sf) __A,
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:269:19: error: use of undeclared identifier '__builtin_ia32_movss'
  return (__m128) __builtin_ia32_movss ((__v4sf) __A,
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:297:19: error: use of undeclared identifier '__builtin_ia32_movss'
  return (__m128) __builtin_ia32_movss ((__v4sf) __A,
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:307:19: error: use of undeclared identifier '__builtin_ia32_movss'
  return (__m128) __builtin_ia32_movss ((__v4sf) __A,
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:351:19: error: use of undeclared identifier '__builtin_ia32_cmpgtps'; did you mean '__builtin_ia32_cmpltps'?
  return (__m128) __builtin_ia32_cmpgtps ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:339:19: note: '__builtin_ia32_cmpltps' declared here
  return (__m128) __builtin_ia32_cmpltps ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:357:19: error: use of undeclared identifier '__builtin_ia32_cmpgeps'; did you mean '__builtin_ia32_cmpleps'?
  return (__m128) __builtin_ia32_cmpgeps ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:345:19: note: '__builtin_ia32_cmpleps' declared here
  return (__m128) __builtin_ia32_cmpleps ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:381:19: error: use of undeclared identifier '__builtin_ia32_cmpngtps'; did you mean '__builtin_ia32_cmpnltps'?
  return (__m128) __builtin_ia32_cmpngtps ((__v4sf)__A, (__v4sf)__B);
                  ^
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/xmmintrin.h:351:19: note: '__builtin_ia32_cmpnltps' declared here
  return (__m128) __builtin_ia32_cmpgtps ((__v4sf)__A, (__v4sf)__B);
                  ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
```

Changed files:
libcodechecker/analyze/analyzers/ctu_triple_arch.py, libcodechecker/analyze/analyzers/analyzer_clangsa.py, libcodechecker/analyze/analyzer_env.py, libcodechecker/analyze/analyzers/analyzer_clang_tidy.py

diff --git a/libcodechecker/analyze/analyzer_env.py b/libcodechecker/analyze/analyzer_env.py
index cd375b30..d5d85b06 100644
--- a/libcodechecker/analyze/analyzer_env.py
+++ b/libcodechecker/analyze/analyzer_env.py
@@ -68,3 +68,33 @@ def get_check_env(path_env_extra, ld_lib_path_extra):
             new_env['LD_LIBRARY_PATH'] = extra_lib
 
     return new_env
+
+
+def extend_analyzer_cmd_with_resource_dir(analyzer_cmd, compiler_resource_dir):
+    """
+    GCC and Clang handles the certain compiler intrinsics for specific
+    instruction sets (like SSE, AVX) differently.  They have their own set of
+    macros in a bunch of include files (e.g. xmmintrin.h) in the include dir
+    of the resource dir of the compiler.  Since we execute the analysis with
+    Clang we must ensure that theses resource headers are included from the
+    proper place. One option to do this is the usage of -resource-dir.  On the
+    other hand, to make the analysis work we also have to add the default
+    includes of the original compiler (which maybe a GCC cross compiler).  We
+    add these default includes of the original compiler with -isystem.
+
+    Our empirical results show that -resource_dir has lower priority than
+    -isystem.  Unfortunately in Clang the implementation about resource
+    includes is very messy, it is merged with the handling of the upcoming
+    modules feature from C++20.  The corresponding functions from Clang:
+        clang::ApplyHeaderSearchOptions
+        HeaderSearch::LookupFile
+        DirectoryLookup::LookupFile.
+    Based on our emprical results, the only solution is to add the resource
+    includes with -isystem before adding the system headers of the original
+    compiler. Since we don't use the -resource_dir switch, it is more explicit
+    and describes our intentions more cleanly if we just simply disable the
+    inludes from the resource dir.
+    """
+    if len(compiler_resource_dir) > 0:
+        analyzer_cmd.extend(['-nobuiltininc',
+                             '-isystem', compiler_resource_dir])
diff --git a/libcodechecker/analyze/analyzers/analyzer_clang_tidy.py b/libcodechecker/analyze/analyzers/analyzer_clang_tidy.py
index 92bdca45..2eb44ef7 100644
--- a/libcodechecker/analyze/analyzers/analyzer_clang_tidy.py
+++ b/libcodechecker/analyze/analyzers/analyzer_clang_tidy.py
@@ -14,6 +14,8 @@ import subprocess
 from libcodechecker.analyze.analyzers import analyzer_base
 from libcodechecker.logger import LoggerFactory
 from libcodechecker.util import get_binary_in_path
+from libcodechecker.analyze.analyzer_env import\\
+    extend_analyzer_cmd_with_resource_dir
 
 LOG = LoggerFactory.get_new_logger('CLANG TIDY')
 
@@ -92,13 +94,8 @@ class ClangTidy(analyzer_base.SourceAnalyzer):
 
             analyzer_cmd.append('-Qunused-arguments')
 
-            # Options before the analyzer options.
-            if len(config.compiler_resource_dir) > 0:
-                analyzer_cmd.extend(['-resource-dir',
-                                     config.compiler_resource_dir,
-                                     '-isystem',
-                                     config.compiler_resource_dir])
-
+            extend_analyzer_cmd_with_resource_dir(analyzer_cmd,
+                                                  config.compiler_resource_dir)
             # Set language.
             analyzer_cmd.extend(['-x', self.buildaction.lang])
 
diff --git a/libcodechecker/analyze/analyzers/analyzer_clangsa.py b/libcodechecker/analyze/analyzers/analyzer_clangsa.py
index 1b937a3c..fd5e2bce 100644
--- a/libcodechecker/analyze/analyzers/analyzer_clangsa.py
+++ b/libcodechecker/analyze/analyzers/analyzer_clangsa.py
@@ -14,6 +14,8 @@ from libcodechecker.analyze.analyzers import ctu_triple_arch
 from libcodechecker.analyze import analyzer_env
 from libcodechecker.logger import LoggerFactory
 from libcodechecker.util import get_binary_in_path
+from libcodechecker.analyze.analyzer_env import\\
+    extend_analyzer_cmd_with_resource_dir
 
 LOG = LoggerFactory.get_new_logger('CLANGSA')
 
@@ -88,11 +90,8 @@ class ClangSA(analyzer_base.SourceAnalyzer):
 
             analyzer_cmd = [config.analyzer_binary]
 
-            if len(config.compiler_resource_dir) > 0:
-                analyzer_cmd.extend(['-resource-dir',
-                                     config.compiler_resource_dir,
-                                     '-isystem',
-                                     config.compiler_resource_dir])
+            extend_analyzer_cmd_with_resource_dir(analyzer_cmd,
+                                                  config.compiler_resource_dir)
 
             # Do not warn about the unused gcc/g++ arguments.
             analyzer_cmd.append('-Qunused-arguments')
diff --git a/libcodechecker/analyze/analyzers/ctu_triple_arch.py b/libcodechecker/analyze/analyzers/ctu_triple_arch.py
index 49bf96df..41c2571e 100644
--- a/libcodechecker/analyze/analyzers/ctu_triple_arch.py
+++ b/libcodechecker/analyze/analyzers/ctu_triple_arch.py
@@ -10,6 +10,8 @@ Helpers for determining triple arch of a compile action
 import shlex
 
 from libcodechecker.analyze.analyzers import analyzer_base
+from libcodechecker.analyze.analyzer_env import\\
+    extend_analyzer_cmd_with_resource_dir
 
 
 def get_compile_command(action, config, source='', output=''):
@@ -17,10 +19,9 @@ def get_compile_command(action, config, source='', output=''):
     for other operations. """
 
     cmd = [config.analyzer_binary]
+    extend_analyzer_cmd_with_resource_dir(cmd,
+                                          config.compiler_resource_dir)
     cmd.extend(action.compiler_includes)
-    if len(config.compiler_resource_dir) > 0:
-        cmd.extend(['-resource-dir', config.compiler_resource_dir,
-                    '-isystem', config.compiler_resource_dir])
     cmd.append('-c')
     cmd.extend(['-x', action.lang])
     cmd.append(config.analyzer_extra_arguments)